Is it possible to group a string every nth character?
For example, suppose I have a string containing the following:
"Hello how are you"
What I'm trying to do is if the user inputs 4, then based on the integer, break into 4 groups and assign those to strings.
1 2 3 4 1 2 3 4 1 2 3 4 1 2
H E L L O H O W A R E Y O U
All the letters that has 1 assigned will be group 1, similarly, all the letters that has 2 assigned will be group 2.
Group 1 - "HOAO", Group 2 - "EHRU", Group 3 - "LOE", Group 4 - "LWY"
Below is what I have so far
import java.util.*;
class groupChar {
static void groupLetters(String str, int n) {
String result="";
for(int i = 0; i < str.length(); i = i + n){
result = result + str.charAt(i);
}
System.out.println(result);
}
public static void main(String[] args) {
Scanner inputMessage = new Scanner(System.in);
System.out.println("Enter string : ");
String message = inputMessage.nextLine();
System.out.println("Enter a number : ");
Scanner inputNumber = new Scanner(System.in);
int number = Integer.parseInt(inputNumber.nextLine());
System.out.println("String is - " + message);
System.out.println("Number is - " + number);
groupLetters(message, number);
}
}
So far I'm only able to create one group based on the user input.
You can approach this problem using Map to track all the groups and using StringBuilder to construct the individual group.
Firstly, we need to generate a HashMap populated with entries having the keys corresponding to the indices of the groups and empty StringBuilders as *values.
Then we have to iterate over the given string, maintaining two indices: i - position in the string and groupId - index of the group. At iteration step, we need to update the current group by appending the current character.
That's how it can be implemented:
public static Map<Integer, StringBuilder> groupLetters(String str, int n) {
Map<Integer, StringBuilder> groupByGroupId = createGroups(n);
for (int i = 0, groupId = 1; i < str.length(); i++, groupId = (groupId++ % n) + 1) {
groupByGroupId.get(groupId).append(str.charAt(i));
}
return groupByGroupId;
}
public static Map<Integer, StringBuilder> createGroups(int n) {
Map<Integer, StringBuilder> groupByGroupId = new HashMap<>();
for (int i = 1; i <= n; i++) {
groupByGroupId.put(i, new StringBuilder());
}
return groupByGroupId;
}
main
public static void main(String[] args) {
for (Map.Entry<Integer, StringBuilder> entry: groupLetters("hellohowareyou", 4).entrySet()) {
System.out.println("Group " + entry.getKey() + " -> " + entry.getValue());
}
}
Output:
Group 1 -> hoao
Group 2 -> ehru
Group 3 -> loe
Group 4 -> lwy
The suggested solution would be to use a map or dictionary with <int,List>. But I recommend the most simple and understandable way without using Map based on your code.
I used the same example as you provided, but starting from 0 would make it easier to understand the code.
0 1 2 3 4 5 6 7 8 9 10 11 12 13
0 1 2 3 0 1 2 3 0 1 2 3 0 1
H E L L O H O W A R E Y O U
The Algorithm:
Group 1 : 0,(0 + (1 x 4)),(0 + (2 x 4)),(0 + (3 x 4)) ...
Group 2 : 1,(1 + (1 x 4)),(1 + (2 x 4)),(1 + (3 x 4)) ...
Group 3 : 2,(2 + (1 x 4)),(2 + (2 x 4)),(2 + (3 x 4)) ...
Therefore, Group a+1 : a, (a + (1 x N)), (a + (2 x N)), (a + (3 x N))...
WHERE the total number of elements in each group is
(total number of Char in string) / (number of droup) + 1
Code
We used a for loop for a AND a for loop for the increment 1,2,3...
Therefore, I have modified your code to meet the requirement :
static void groupLetters(String str,int n) {
//Remove the string space and to UPPER CASE
str = str.toUpperCase().replaceAll("\\s+","");
for(int a = 0; a < n; a++){
String result = "";
//Get the Char in Group a with the algorithm mentioned above
for(int i = 0; i < str.length() / n + 1; i++){
if(a + (i * n) < str.length()){
result = result + str.charAt(a + (i * n));
}
}
System.out.println("Group "+ (a + 1) + ": " + result);
}
}
public static void main(String[] args) {
Scanner inputMessage = new Scanner(System.in);
System.out.println("Enter string : ");
String message = inputMessage.nextLine();
System.out.println("Enter a number of group gonna break into : ");
Scanner inputNumber = new Scanner(System.in);
int number = Integer.parseInt(inputNumber.nextLine());
System.out.println("String is - " + message);
System.out.println("Number of Group is - " + number);
groupLetters(message,number);
}
OUTPUT:
String is - Hello how are you
Number of Group is - 4
Group 1: HOA
Group 2: EHR
Group 3: LOE
Group 4: LWY
Splitter can be used to split text by length
com.google.common.base.Splitter , see -> https://www.geeksforgeeks.org/splitter-class-guava-java/
I slightly modified the code :
import java.util.Scanner;
import com.google.common.base.Splitter;
public class test {
public static String result="";
public static int index = 0;
static void groupLetters(String str, int n) {
str = str.replaceAll("\\s", "");
Iterable<String> fullString = Splitter.fixedLength(n).split(str);
int length = str.length() % n == 0 ? str.length() / n : (str.length() / n) + 1;
for(int i = 0; i < length + 1; i++){
fullString.forEach(s->{
if(s.length()>index){
result+=s.charAt(index)+"";
}
});
result+=" ";
index++;
}
System.out.println(result);
}
public static void main(String[] args) {
Scanner inputMessage = new Scanner(System.in);
System.out.println("Enter string : ");
String message = inputMessage.nextLine();
System.out.println("Enter a number : ");
Scanner inputNumber = new Scanner(System.in);
int number = Integer.parseInt(inputNumber.nextLine());
System.out.println("String is - " + message);
System.out.println("Number is - " + number);
groupLetters(message, number);
}
}
Related
I'm writing a simple vowel-counter and was wondering if there's a cleaner alternative (possibly a loop?) to replace all of the else if's when comparing s to the various vowels.
I can't think of a simple way to do this effectively as the number of each vowel must be shown individually. It would be very simple if it was just a total vowel count.
I'm quite new to Java so I don't know what can be used to clean this up. If this is the best option, then I am contempt -- but I love cleaning up code where it can be!
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int A = 0, E = 0, I = 0, O = 0, U = 0;
System.out.print("Type a single word > ");
String word = input.next();
for (int i = 0; i < word.length(); i++) {
String s = word.substring(i, i + 1);
if (s.equalsIgnoreCase("A")) { A++; }
else if (s.equalsIgnoreCase("E")) { E++; }
else if (s.equalsIgnoreCase("I")) { I++; }
else if (s.equalsIgnoreCase("O")) { O++; }
else if (s.equalsIgnoreCase("U")) { U++; }
}
int total = A + E + I + O + U;
System.out.println("\n'" + word + "' has...\n" + A + " A's\n" + E + " E's\n" + I + " I's\n" + O + " O's\n" + U + " U's\nTotal vowels: " + total + "\n");
input.close();
}
}
Input:
Coding
Output:
'Coding' has...
0 A's
0 E's
1 I's
1 O's
0 U's
Total vowels: 2
Here is a less repetitive way to code it, using an int array for the counts, and a string holding the sequence of vowels.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Type a single word > ");
String word = input.next();
String vowels = "AEIOU";
int[] counts = new int[vowels.length()];
int total = 0;
for (int i = 0; i < word.length(); i++) {
int index = vowels.indexOf(Character.toUpperCase(word.charAt(i)));
if (index >= 0) {
++counts[index];
++total;
}
}
System.out.printf("%n'%s' has...%n", word);
for (int i = 0; i < counts.length; ++i) {
System.out.printf("%s %s's%n", counts[i], vowels.charAt(i));
}
System.out.printf("Total vowels: %s%n", total);
}
}
Output:
Type a single word > Coding
'Coding' has...
0 A's
0 E's
1 I's
1 O's
0 U's
Total vowels: 2
You could avoid a lot of repetition by using a Map that associates vowels (keys) to their frequencies within the word passed at runtime (values).
It is worth noting that a LinkedHashMap is used in the below example as to preserve the insertion order of keys for printing at the end of the program - as would not be the case with a HashMap.
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Define Map to map vowels to frequencies
Map<Character, Integer> vowels = new LinkedHashMap<Character, Integer>();
vowels.put('A', 0);
vowels.put('E', 0);
vowels.put('I', 0);
vowels.put('O', 0);
vowels.put('U', 0);
// Get input from user
System.out.print("Type a single word > ");
String word = input.next();
// Iterate across word
for (int i = 0; i < word.length(); i++) {
String c = word.substring(i, i+1); // Get current char
for (Character key : vowels.keySet()) { // Iterate across vowels
if (c.equalsIgnoreCase(key.toString())) {
vowels.put(key, vowels.get(key)+1); // Increment vowel frequency if matched
break; // Break inner loop and move to next char in word
}
}
// Sum total
int total = 0;
for (Character key : vowels.keySet()) {
total += vowels.get(key);
}
// Print results to console
System.out.println("\'" + word + "\'" + " has...");
for (Character key : vowels.keySet()) {
System.out.println(vowels.get(key) + " " + key + "\'s");
}
System.out.println("Total vowels: " + total);
input.close();
}
}
}
With the scanner I want to read the index of a char and then remove it from the string. There is only one problem: If the char comes multiple times in the string, .replace() removes all of them.
For example I want to get the index of first 't' from the String "Texty text" and then remove only that 't'. Then I want to get index of second 't' and then remove it.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
String text = "Texty text";
Scanner sc = new Scanner(System.in);
int f = 0;
int x = 0;
while(f<1){
char c = sc.next().charAt(0);
for(int i = 0; i<text.length();i++){
if(text.charAt(i)==c){
System.out.println(x);
x++;
}
else{
x++;
}
}
}
System.out.println(text);
}
}
You could use replaceFirst:
System.out.println(text.replaceFirst("t", ""));
Probably you are looking for something like the following:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
String text = "Texty text";
String copy = text;
Scanner sc = new Scanner(System.in);
while (true) {
text = copy;
System.out.print("Enter a character from '" + text + "': ");
char c = sc.next().charAt(0);
for (int i = 0; i < text.length(); i++) {
if (Character.toUpperCase(text.charAt(i)) == Character.toUpperCase(c)) {
System.out.println(c + " was found at " + i);
text = text.substring(0, i) + "%" + text.substring(i + 1);
System.out.println("After replacing " + c + " with % at " + i + ": " + text);
}
}
}
}
}
A sample run:
Enter a character from 'Texty text': x
x was found at 2
After replacing x with % at 2: Te%ty text
x was found at 8
After replacing x with % at 8: Te%ty te%t
Enter a character from 'Texty text': t
t was found at 0
After replacing t with % at 0: %exty text
t was found at 3
After replacing t with % at 3: %ex%y text
t was found at 6
After replacing t with % at 6: %ex%y %ext
t was found at 9
After replacing t with % at 9: %ex%y %ex%
Enter a character from 'Texty text':
Try using txt.substring(x,y)
x = usually 0 , but x is first start index
y = this is what you want to delete for example for the last word of string write this code:
txt.substring(0, txt.length() - 1)
Since you are specifying indices, it is possible that you may want to replace the second of a particular character. This does just that by ignoring the ones before it. This returns an Optional<String> to encase the result. Exceptions are thrown for appropriate situations.
public static void main(String[] args) {
// Replace the first i
Optional<String> opt = replace("This is a testi", 1, "i", "z");
// Replace the second i (and so on).
System.out.println(opt.get());
opt = replace("This is a testi", 2, "i", "z");
System.out.println(opt.get());
opt = replace("This is a testi", 3, "i", "z");
System.out.println(opt.get());
opt = replace("This is a testi", 4, "i", "z");
System.out.println(opt.get());
}
public static Optional<String> replace(String str, int occurrence, String find, String repl) {
if (occurrence == 0) {
throw new IllegalArgumentException("occurrence <= 0");
}
int i = -1;
String strCopy = str;
while (occurrence-- > 0) {
i = str.indexOf(find, i+1);
if (i < 0) {
throw new IllegalStateException("insufficient occurrences of '" + find + "'");
}
}
str = str.substring(0,i);
return Optional.of(str + strCopy.substring(i).replaceFirst(find, repl));
}
assignment:
Write a program that reads in integers between 1 and 100 from the user and counts the
occurrences of each number. The user input ends when they enter a 0.
You must use an enhanced for-loop to solve this problem.
If a number occurs more than 1 time use the plural word “times” instead of “time”. Do not display numbers that were not entered.
I know and understand why my code's current output below appears with duplicates. The print logic is inside the for-each loop code block. If I close the code block I am no longer able to use the variables I initialized inside the loop. I have tried everything I can think of. Any suggestions would be appreciated
current output:
- 1 occurs 1 time,
- 1 occurs 2 times
- 2 occurs 1 time
- 2 occurs 2 times
- 3 occurs 1 time
- 3 occurs 2 times
needed output:
- 1 occurs 2 times
- 2 occurs 2 times
- 3 occurs 2 times
package com.company;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] numbers = new int[10];
System.out.print("Enter Integers:");
for (int i = 0; i < numbers.length; i++) {
numbers[i] = in.nextInt();
if (numbers[i] == 0) {
break;
}
}
enhancedLoop(numbers);
}
private static void enhancedLoop(int[] numbers) {
int[] counts = new int[101];
for (int value : numbers) {
counts[value]++;
if (value > 0)
if (counts[value]> 1)
System.out.println(value + " occurs " + counts[value]+ " times");
else
System.out.println(value + " occurs " + counts[value] + " time");
}
}
Variables are only available in the block in which they are declared. Move the output after the for loop and iterate over counts to display the values:
for (int i = 0, c = counts.length; i < c; ++i) {
if (counts[i] > 0) {
if (counts[i] > 1) {
System.out.println(value + " occurs " + counts[i]+ " times");
} else {
System.out.println(value + " occurs " + counts[i]+ " time");
}
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] numbers = new int[10];
System.out.print("Enter Integers:");
for (int i = 0; i < numbers.length; i++) {
numbers[i] = in.nextInt();
if (numbers[i] == 0) {
break;
}
}
enhancedLoop(numbers);
}
private static void enhancedLoop(int[] numbers) {
int[] counts = new int[101];
for (int value : numbers) {
counts[value]++;
if (value > 0)
if (counts[value]> 1)
System.out.println(value + " occurs " + counts[value]+ " times");
else
System.out.println(value + " occurs " + counts[value] + " time");
}
}
You can do this effectively using the below steps:
(1) Identify the unique numbers first
(2) Find the number of times each unique number occurs
So, you need to change your enhancedLoop(int[] numbers) method as shown below to achieve the result:
private static void enhancedLoop(int[] numbers) {
//convert the array to a list to make computations easier by using streams
List<Integer> numbersList = Arrays.stream(numbers).boxed().collect(Collectors.toList());
//Get the unique numbers in the list
List<Integer> uniqueNumbers = numbersList.stream().distinct().collect(Collectors.toList());
//Now find out number of times each each unique number occured
for(int number : uniqueNumbers) {
long times = numbersList.stream().filter(num -> num == number).count();
System.out.println(number+" occurs "+times);
}
}
lets try to do this without lamdas, using simply a hashmap instead of arrays
import java.util.Scanner;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
HashMap<Integer, Integer> numbers = new HashMap<Integer, Integer>();
int tmp=0;
System.out.print("Enter Integers:");
//read a maximum of 10 int
for (int i = 0; i < 10; i++) {
tmp = in.nextInt();
//if we read a 0 we quit
if (tmp == 0) {
break;
}
//if we already saw the number we up the counter
if(numbers.containsKey(tmp)){
numbers.put(tmp, numbers.get(tmp)+1);
}else{
//otherwise we just add the new int
numbers.put(tmp, 1);
}
}
//call the print loop
enhancedLoop(numbers);
}
private static void enhancedLoop(HashMap<Integer, Integer> numbers) {
//you print what you counted
for(Map.Entry<Integer, Integer> entry : numbers.entrySet()) {
System.out.print(entry.getKey() + " occurs " + entry.getValue() + " time");
if (entry.getValue()>1)
System.out.print("s");
System.out.println("");
}
}
When the user enters 0, the program is supposed to stop. I can't figure out how to do this. For example:
Enter the integers between 1 and 100: 2 5 6 5 4 3 23 43 2 0
2 occurs 2 times
3 occurs 1 time
4 occurs 1 time
5 occurs 2 times
6 occurs 1 time
23 occurs 1 time
43 occurs 1 time
My code prints the 0.
public class CountOccurrences {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter ten integers between 1 and 100: ");
String userInput = input.nextLine();
//this splits the user input into an array using a space
String[] inputString = userInput.split(" ");
String[] previousValues = new String[inputString.length];
int count = 1;
//Compare elements and update count for new string
for (int i = 0; i < inputString.length; i++) {
for (int j = i+ 1; j < inputString.length; j++) {
if (inputString[i].equals(inputString[j]) && notFound (previousValues, inputString[i]) { `
count++;
}
}
//Prints only unique strings
if(!userInput.equals("0")){
if (notFound(previousValues,inputString[i])) {
if (count>1) {
System.out.println(inputString[i] + " occurs " + count + " times");
} else {
System.out.println(inputString[i] + " occurs " + count + " time");
}
count = 1;
}
if (notFound(previousValues,inputString[i])) {
previousValues[i] = inputString[i];
}
}}
}
//This method returns a boolean value. It is true if the string is not in the array and vice versa
public static boolean notFound(String[] pastValues, String currentString) {
boolean valueNotFound = true;
int index = 0;
while(index < pastValues.length && valueNotFound) {
if ((pastValues!= null) &&(currentString.equals(pastValues[index]))) {
valueNotFound = false;
}
index++;
}
return valueNotFound;
}
//Method for printing an array
public static void printArray(String [] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+ " ");
}
}
}
You can do that by adding an else condition and using System.exit(0) and tell the user that the program is going to terminate.
static void exit(int status) Terminates the currently running program or Java Virtual Machine.
status 0 indicates that the program execution completed without exceptions.
You can look at the API here
I have create a sample program in java .The concepts is split String value to generate Array list in one by one its means total string is input below:
Step one Total size:
Sting numberlist ="1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890........................1234567890";
ArrayList aList= new ArrayList(Arrays.asList(numberlist.split(",")));
for (int i = 0;i<aList.size();i++)
{
System.out.println(" new number-->" + aList.get(i));
// Toast.makeText(getApplicationContext(),"number is"+aList.get(i),Toast.LENGTH_SHORT).show();
}
I got the answer +alist.get(i) = 300 ,Than Step two know i having total size 300
The process is split the value one by one means
Display First 100 value 1234567890,1234567890,1234567890,.....
Display Second 100 value 1234567890,1234567890,1234567890,.....
Display Third 100 value 1234567890,1234567890,1234567890,.....
Sample programs is:
String numberlist="1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890........................1234567890";
int splitNumber = 100;
int length = numberlist.length();
ArrayList<String>splitList = new ArrayList<String>();
int splitCount = 0;
for(int i = 1 ; i<= length;i++)
{
splitCount++;
boolean last = false;
if(i==length)
{
last = true;
}
if((splitNumber == splitCount) || last)
{
String number = numberlist.substring(splitList.size()*splitNumber,i);
number = number.endsWith(",") ? number.substring(0,number.length()) : number;
number = number.startsWith(",") ? number.substring(1,number.length()) : number;
splitList.add(number);
splitCount = 0;
}
}
for(String number : splitList)
{
System.out.println();
System.out.println("Display First 100 value"+number);
}
}
but something wrong in the program don't know where is the problem anyone given me solutions.
I need my output is below:
Display First 100 value 1234567890,1234567890,1234567890,.....
Display Second 100 value 1234567890,1234567890,1234567890,.....
Display Third 100 value 1234567890,1234567890,1234567890,.....
its like one by one..
Note : sorry my grammar mistake..
Judging by your question, I assume the number of elements is divisible by splitNumber. There are a few approaches to this. Here I show one using modulo to create groups of size splitNumber and int division to get the group number:
public class Test {
public static void main(String[] args) throws Exception {
String numberlist = "1234,1234,1234,1234,1234,1234,1234,1234,1234";
int splitNumber = 3;
ArrayList<String> splitList = new ArrayList<String>(Arrays.asList(numberlist.split(",")));
if (splitList.size() % splitNumber != 0)
throw new Exception("Number of elelemnts not divisable by split number");
for (int i = 0; i < splitList.size(); i += splitNumber) {
System.out.print(((i / splitNumber) + 1) + " group of " + splitNumber +": ");
for (int j = 0; j < splitNumber; j++) {
System.out.print(splitList.get(i + j) +", ");
}
System.out.println();
}
}
}
Output:
1 group of 3: 1234, 1234, 1234,
2 group of 3: 1234, 1234, 1234,
3 group of 3: 1234, 1234, 1234,
Perform your own formatting.
If I understand the question correctly.. You can display 100 elements and whatever is leftover like this.
for (int i = 0; i < s.length(); i += 100) {
if ((i+100) > s.length()) {
System.out.println(s.substring(i, s.length()));
} else {
System.out.println(s.substring(i, i + 100));
}
}