I have a string:
String text = "Nothing right in my brain. Nothing left in my brain"
I want to create a new string text2 that has 2-4 random new line from previous, such as:
"Nothing \n right \n in my brain. \n Nothing left in my brain"
or
"Nothing right in \n my brain. Nothing left in \n my brain"
How to create a new string with random new line between the words?
I am thinking to get the index of whitespace, in order to insert new line after random whitespace. But I only keep getting the first whitespace index.
Anyone know better approach to solve this? Thank you.
There are three stages to your problem, splitting the String, inserting randomness and using them together...
Splitting a String
Break it into words with String.split(), which creates an array of Strings (in this case words) by spaces.
String[] words = text.split(" "); //Split by spaces
then rebuild your String with newlines added for instance:-
StringBuiler sb = new StringBuilder();
for (String word : words)
{
sb.append(word + "\n");
}
String text2 = sb.toString();
In this case you will insert a newline in between every word and save the result in text2.
Inserting Randomness
You could just create a Random object...
Random random = new Random();
Then use it in the code that inserts your newline, like so...
//Randomly add or don't add a newline (Compacted with a ternary operator instead of an 'if')
sb.append(word + (random.nextBoolean() ? "\n" : ""));
Bringing it together (TLDR)
Then all you need to do is maintain a count of inserted newlines and limit them to that. So your code becomes:-
int requiredNewlines = random.nextInt(2 - 5) + 2; //Number between 2-4
for (String word : words) //For each word
{
sb.append(word); //Add it
if (requiredNewlines >= 0 && random.nextBoolean())
{
//Randomly add newline if we haven't used too many
sb.append("\n");
requiredNewlines--;
}
}
String text2 = sbAppen.toString();
Additionally
Although the randomness in this example fits your purpose here it is not the ideal implementation of random (as mentioned in the comments), in that there is more bias towards one appearing nearer the start of the String than the end and that there no chance of it appearing before the first word.
There is also another option of using StringTokenizer instead of String.split() which I much prefer but it doesn't deal with regex and is falling out of use, so I've changed my answer to use String.split()
First you need a new random from 2-4:
int max = 4;
int min = 2;
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
After split string into words:
String[] words = text.split(" ");
Then, get 4 different numbers from 1 to words.length
ArrayList<Integer> randomPositions = new ArrayList<Integer>(randomNum);
max = words.length;
min = 1;
for (int count = 0; count < randomNum; count ++) {
int random = rand.nextInt((max - min) + 1) + min;
if (randomPositions.contains(random)) count --;
else randomPositions.add(random);
}
Finally put \n in positions when rebuilding the array:
StringBuilder result = new StringBuilder();
for (int count = 0; count < max; count ++) {
result.append(words[count]);
if (randomPositions.contains(count))
result.append("\n");
else
result.append(" ");
}
Check this working demo
Output1:
Nothing right in my
brain. Nothing
left in my brain
Output2:
Nothing right
in my brain. Nothing left
in my
brain
Output3:
Nothing right in my brain. Nothing left
in my brain
You can only get either the first index using indexOf() or the last index using lastIndexOf() methods.
But as a workaround you can use text.indexOf(" ", randomInt);. This will give you the first index of " " after the randomInt index.
String str = "Nothing right in my brain. Nothing left in my brain";
String[] split = str.split(" ");
for (int i = 0; i < split.length; i++) {
int flag = ((int) (Math.random() * 10)) % 2;
if (flag == 0) {
split[i] = split[i] + "\n";
}
}
str="";
for (int i = 0; i < split.length; i++) {
str += split[i]+" ";
}
First you could get a random index where to put the new line
Random rand = new Random();
String[] words = text.split(' ');
for(int i = 0; i < 3; i++){
int index = rand.nextInt(words.length());
words[index] = "\n" + words[index];
}
text = Arrays.toString(words);
and at the end you will have 3 new lines on random places in your text string
EDIT: one way the result to be without commas is this one:
text = Arrays.toString(words).replaceAll(", ", " ");
Generate String with insertions at different positions:
public static String generateString(String inputString, String delimiter,
String insString, int[] insIndexes) {
String[] splittedString = inputString.split(delimiter);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < splittedString.length; i++) {
sb.append(splittedString[i]);
if (Arrays.binarySearch(insIndexes, i + 1) >= 0)
sb.append(delimiter + insString);
sb.append(delimiter);
}
return sb.toString();
}
Invocation Part :
String inputString = "Nothing right in my brain. Nothing left in my brain";
String delimiter = " "; // input String delimiter
String insString = "\n"; // insertion String
int[] insIndexes = { 2, 4, 6, 8 }; // insertion indexes
String outputString = generateString(inputString, delimiter, insString, insIndexes);
Related
I am trying to reduce the string array by using a for a loop. This is an example I tried to do
User string input: Calculus
User input:5
output: CalcuCalcCalCaC
I have turned the string to a char array but the issue presents itself when trying to print them out multiple times. It only prints once and has the right starting output.
input string: Oregon
input number: 4
output: Oreg
I notice my for loop says that it is not looping when I hover over it on the IDE that I downloaded from JetBrains.
I tried different combinations of decrementing and incrementing but could not get that "for statement is not looping". Other than that I have tried different ways to do something in the for loop but I don't think anything needs to be done for now if the for loop is not looping then, right?
So my question is, how to reduce a string or char array and print the decrement value over and over again?
Here is my code so far for it.
public String wordDown(String userString, int userNum)
{
String stringModded = userString.substring(0, userNum);
char[] charArray = stringModded.toCharArray();
char repeat = ' ';
for(int i = 0; i<userNum; ++i)
{
repeat = (char) (repeat +charArray[i]);
charArray[i] = repeat;
for(int j = 1; i > charArray.length; ++j)
{
String modWord = String.valueOf(charArray[i + 1]);
return modWord;
}
}
return null;
}
public static void main(String[] args)
{
int userNumber;
String userString;
RandomArrayFunctionalities ranMethod = new RandomArrayFunctionalities();
Scanner in = new Scanner(System.in);
System.out.println("\nEnter a word:");
userString = in.next();
System.out.println("\nEnter a number within the word scope that you just enter:");
userNumber = in.nextInt();
System.out.println(ranMethod.wordDown(userString, userNumber));
}
You do not need to modify the original array. Use a StringBuilder to concatenate the successive parts of the word. Use the String.substring(int,int) method to pull out those parts. The example that follows uses a decrementing index to generate the successively smaller substrings.
public String wordDown(String word, int userNum) {
StringBuilder sb = new StringBuilder();
for (int length = userNum ; length > 0 ; --length) {
sb.append(word.substring(0, length));
}
return sb.toString();
}
I think you are over complicating things, you don't need a char array at all and you only need a single loop, and a single return statement:
public String wordDown(String userString, int userNum) {
String finalString = "";
for (int i = 0; i < userNum; ++i) {
finalString = finalString + userString.substring(0, userNum - i);
}
return finalString;
}
Simply loop up to the inputted number and substring from 0 to inputtedNumber - loopCounter and append the result to the previously held String value.
Example Run:
Enter a word:
Calculus
Enter a number within the word scope that you just enter:
5
CalcuCalcCalCaC
Sidenote:
Technically you would want to use StringBuilder instead of appending String in a loop, but that is probably out of the scope of this question. Here is that version just for reference:
public String wordDown(String userString, int userNum) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < userNum; ++i) {
sb.append(userString.substring(0, userNum - i));
}
return sb.toString();
}
The code below works when number of strings in array is odd (3,5,7) however it does not work when the number is even. For example, if I use "my is the name" I get output
name is the name
public void randomTest() {
String str ="my is name";
//Step1: split so that I can get them in in array
String [] arrStr= str.split(" ");
for(int i=0;i<arrStr.length;i++){
//Step2: Using temp swap 1st and last
String temp = arrStr[0];
arrStr[0] = arrStr[arrStr.length-1];
arrStr[arrStr.length-1] = temp;
System.out.print(arrStr[i]+" ");
}
}
Any idea how can I make it work for even number of Strings? Thank You.
Since Arvind Kumar Avinash has shared the fixed solution, I just like to offer an alternative option: After splitting the string into String array, maybe you can simply swap the last and first values, and then join them together:
String str ="my is the name";
// split
String[] arrStr= str.split(" ");
// swap
String temp = arrStr[0];
arrStr[0] = arrStr[arrStr.length - 1];
arrStr[arrStr.length - 1] = temp;
// join them back
str = String.join(" ", arrStr);
System.out.println(str); // name is the my
You need to iterate the loop only for half of the length of the array i.e.
for (int i = 0; i < arrStr.length / 2; i++)
Also, you need to use the counter variable, i instead of the fixed values 0 and 1. Make sure to limit the indices in the range of 0 to length_of_array - 1 which is the range of indices of an array in Java.
Do it as follows:
public class Main {
public static void main(String[] args) {
String str = "my is the name";
String[] arrStr = str.split(" ");
// Swap the elements of the array
for (int i = 0; i < arrStr.length / 2; i++) {
String temp = arrStr[i];
arrStr[i] = arrStr[arrStr.length - i - 1];
arrStr[arrStr.length - i - 1] = temp;
}
// Display the array
for (int i = 0; i < arrStr.length; i++) {
System.out.print(arrStr[i] + " ");
}
}
}
Output:
name the is my
If you want to swap only the first word with the last word, you do not need a loop. You can simply so it as follows:
public class Main {
public static void main(String[] args) {
String str = "my is the name";
String[] arrStr = str.split(" ");
// Swap the first and the last words
String temp = arrStr[0];
arrStr[0] = arrStr[arrStr.length - 1];
arrStr[arrStr.length - 1] = temp;
// Display the array
for (int i = 0; i < arrStr.length; i++) {
System.out.print(arrStr[i] + " ");
}
}
}
Output:
name is the my
What you are currently doing is swapping the first and last elements n times, where n is the size of the array. This makes it so that when you have an even number of elements, for example, 2, then you are swapping the first and last elements, and then swapping them back to their original position, which is unswapped. This is also why it is working for an odd number of elements since you are swapping the first and last elements an even number of times and then once more. If you just want to swap the first and last elements, you can simply get rid of the for loop that you have and it will work properly.
public void randomTest() {
String str ="my is name";
//Step1: split so that I can get them in in array
String [] arrStr= str.split(" ");
//Step2: Using temp swap 1st and last
String temp = arrStr[0];
arrStr[0] = arrStr[arrStr.length-1];
arrStr[arrStr.length-1] = temp;
}
Afterwards, if you want to merge the strings back together, you can use
str = String.join(" ", arrStr);
or a StringBuilder object like so.
StringBuilder sb = new StringBuilder(arrStr[0]);
for (int i = 0; i < arrStr.length; i++) {
sb.append(" ").append(arrStr[i]);
}
str = sb.toString();
The effect of either of these will turn my name is foo into foo name is my, basically swapping the first and last words, and will work for a string with any length or number of words.
Easiest way is to substring first and last word from the sentence.
int first = name.indexOf(' '); // first "space" character that occurs
int last = name.lastIndexOf(' '); // last "space" character that occurs
String firstWord = name.substring(0, first); // substring first word from index 0 to index of first "space" character
String lastWord = name.substring(last, name.length()-1); // substring last word from index the of last "space" character to higher index o sentence
String midSentece = name.substring(first, last); // substring rest of the sentence
System.out.println(lastWord + midSentece + firstWord);
I need to create a program that counts the frequency of characters in a text file, as well as the number of paragraphs words and sentences.
I have a problem where when my program outputs the frequency of the letters the program outputs multiple outputs for each letter in the alphabet.
Output should be like this:
if input was "hello world!"
(should output this for all letters of the alphabet):
The letter a has been found 0 times
the letter b has been found 0 times
(until it reaches the letters that appear and then shows how many times they appear)
number of paragraphs: 1
number of sentences: 1
number of characters:10
number of words: 2
I have been working on this for weeks now and still can't find a solution.
package SuperCounter2;
import java.io.*;
public class SuperCounter2 {
public static void main(String[] args) throws IOException {
File file = new File("//Users//4617621//Desktop//This is the most stupid assignment");
FileInputStream fileStream = new FileInputStream(file);
InputStreamReader input = new InputStreamReader(fileStream);
BufferedReader reader = new BufferedReader(input);
String line;
int countWord = 0;
int sentenceCount = 0;
int characterCount = 0;
int paragraphCount = 1;
int whitespaceCount = 0;
while ((line = reader.readLine()) != null) {
int ci, i, j, k, l = 0;
char c, ch;
i = line.length();
if (line.equals("")) {
paragraphCount++;
}
if (!(line.equals(""))) {
characterCount += line.length();
String[] wordList = line.split("\\s+");
countWord += wordList.length;
whitespaceCount += countWord - 1;
String[] sentenceList = line.split("[!?.:]+");
sentenceCount += sentenceList.length;
}
int counter = 0;
for (int m = 0; m < line.length(); m++) {
counter++;
}
for (c = 'A'; c <= 'z'; c++) {
k = 0;
for (j = 0; j < i; j++) {
ch = line.charAt(j);
if(ch == c) {
k++;
System.out.println(" the character " + c + " has occured " + k + " times");
}
}
}
}
System.out.println("Total word count = " + countWord);
System.out.println("Total number of sentences = " + sentenceCount);
System.out.println("Total number of characters = " + characterCount);
System.out.println("Number of paragraphs = " + paragraphCount);
System.out.println("Total number of whitespaces = " + whitespaceCount);
}
}
I think that you could see this as simply counting the number of periods, spaces, carriage returns, etc.
It might be easier to do this by taking it a letter at a time instead of a word at a time.
The only place it would get tricky (where you need to look at more than one thing at a time) is cases where there might be "word1.word2", "word1. word2" or "word1. word2" (two spaces). For those you might have to keep a flag that said if the previous character was a "word separator"(Period, space, c/r) then don't count another word.
Otherwise it seems pretty straight forward. Look at the character, if it is a period add it to the line count&word count, if it's a space add it to the word count, if it's a c/r add it to the paragraph, and word counts, and then track each letter (probably in a Map)
The inside of the loop should be about 5 lines of code if you count the flag manipulation.
Not writing code because this sounds like homework.
PS: It actually seems like a pretty cool assignment :)
For example, the user enters "1 2 3 4", how do I extract those four numbers and put them into separate spots in an array?
I'm just a beginner so please excuse my lack of knowledge.
for (int i = 0; i < students; i++) {
scanner.nextLine();
tempScores[i] = scanner.nextLine();
tempScores[i] = tempScores[i] + " ";
tempNum = "";
int scoreCount = 0;
for (int a = 0; a < tempScores[i].length(); a++) {
System.out.println("Scorecount " + scoreCount + " a " + a );
if (tempScores[i].charAt(a) != ' ') {
tempNum = tempNum + tempScores[i].charAt(a);
} else if (tempScores[i].charAt(a) == ' ') {
scores[scoreCount] = Integer.valueOf(tempNum);
tempNum = "";
scoreCount ++;
}
}
You can use String.split(String) which takes a regular expression, \\s+ matches one or more white space characters. Then you can use Integer.parseInt(String) to parse the String(s) to int(s). Finally, you can use Arrays.toString(int[]) to display your int[]. Something like
String line = "1 2 3 4";
String[] tokens = line.split("\\s+");
int[] values = new int[tokens.length];
for (int i = 0; i < tokens.length; i++) {
values[i] = Integer.parseInt(tokens[i]);
}
System.out.println(Arrays.toString(values));
Outputs
[1, 2, 3, 4]
If you are very sure that the numbers will be separated by space then you could just use the split() method in String like below and parse individually :
String input = sc.nextLine(); (Use an sc.hasNextLine() check first)
if (input != null || !input.trim().isEmpty()) {
String [] numStrings = input.split(" ");
// convert the numbers as String to actually numbers by using
Integer.parseInt(String num) method.
}
I am supposed to do this :
For an input number print frequency of each number in the order of its occurrence.For eg :
Input:56464
Output:
Number-Frequency
5 -1
6 -2
4 -2
I cannot use any other libraries except java.lang and Scanner to input
So I tried this :
package practice2;
import java.util.Scanner;
public class DigitFrequency2
{
private static Scanner sc;
public static void main(String[] args)
{
sc = new Scanner(System.in);
System.out.println("Enter an integer number");
String sb = sc.nextLine();
System.out.println("Number\tFrequency");
int i,x,c = 0;
for(i=0;i<sb.length();i++)
{
c = 0;
for(x = i+1;x<sb.length();x++)
{
if(sb.charAt(i) == sb.charAt(x) && sb.charAt(i) != '*' && sb.charAt(x) != '*')
{
c++;
sb.replace(sb.charAt(x),'*');
}
}
if(c>0)
{
System.out.println(sb.charAt(i)+" \t"+c);
}
}
}
}
Number Frequency
6 1
4 1
Where am I going wrong please help.
Simple way is this. Won't bother commenting as it is clear whats going on.
Scanner in = new Scanner(System.in);
while (true) {
System.out.print("Input String: ");
String line = in.nextLine();
while (!line.isEmpty()) {
char c = line.charAt(0);
int length = line.length();
line = line.replace(String.valueOf(c), "");
System.out.println(c + " " + (length - line.length()));
}
}
There are few problems with sb.replace(sb.charAt(x),'*');:
replace replaces all characters, not just first one which is why your c can't be grater than 1.
Strings are immutable so since replace can't edit original string, it returns new one with replaced characters which you can store back in sb reference.
Anyway if you would be able to use other Java resources beside java.lang.* or java.util.Scanner simple approach would be using Map which will map character with number of its occurrences. Very helpful here is merge method added in Java 8 allows us to pass key initialValue combination of old and new value
So your code can look like:
String sb = ...
Map<Character, Integer> map = new TreeMap<>();
for (char ch : sb.toCharArray()) {
map.merge(ch, 1, Integer::sum);
}
map.forEach((k, v) -> System.out.println(k + "\t" + v));
Problem is that as mentioned, String is immutable, so String.replace() just returns a new string and it does not (cannot) modify the original. Either you should use StringBuilder, or store the returned value (e.g. sb = sb.replace(sb.charAt(x),'*');).
Going further, since you initialize c with 0, it will stay 0 if there is no other occurrence of the character in question (sb.charAt(i)), so your algorithm won't detect and print digits that occur only once (because later you only print if c > 0).
Counting occurrences (frequency) of characters or digits in a string is a simple operation, it does not require to create new strings and it can be done by looping over the characters only once.
Here is a more efficient solution (one of the fastest). Since digits are in the range '0'..'9', you can create an array in which you count the occurrences, and by looping over the characters only once. No need to replace anything. Order of occurrence is "remembered" in another order char array.
char[] order = new char[10];
int[] counts = new int[10];
for (int i = 0, j = 0; i < sb.length(); i++)
if (counts[sb.charAt(i) - '0']++ == 0)
order[j++] = sb.charAt(i); // First occurrence of the digit
And print in order, until the order array is filled:
System.out.println("Number\tFrequency");
for (int i = 0; order[i] != 0; i++)
System.out.println(order[i] + "\t" + counts[order[i] - '0']);
Example output:
Enter an integer number
56464
Number Frequency
5 1
6 2
4 2
For completeness here's the complete main() method:
public static void main(String[] args) {
System.out.println("Enter an integer number");
String sb = new Scanner(System.in).nextLine();
char[] order = new char[10];
int[] counts = new int[10];
for (int i = 0, j = 0; i < sb.length(); i++)
if (counts[sb.charAt(i) - '0']++ == 0)
order[j++] = sb.charAt(i); // First occurrence of the digit
System.out.println("Number\tFrequency");
for (int i = 0; order[i] != 0; i++)
System.out.println(order[i] + "\t" + counts[order[i] - '0']);
}
Note:
If you would want to make your code safe against invalid inputs (that may contain non-digits), you could use Character.isDigit(). Here is only the for loop which is safe against any input:
for (int i = 0, j = 0; i < sb.length(); i++) {
char ch = sb.charAt(i);
if (Character.isDigit(ch)) {
if (counts[ch - '0']++ == 0)
order[j++] = ch; // First occurrence of ch
}
}
This should be a good code to print frequency using user input:
public static void main(String args[])
{
System.out.println("Please enter numbers ");
String time = in.nextLine(); //USER INPUT
time = time.replace(":", "");
char digit[] = {time.charAt(0), time.charAt(1), time.charAt(2), time.charAt(3)};
int[] count = new int[digit.length];
Arrays.sort(digit);
for (int i = 0; i < digit.length; i++)
{
count[i]++;
if (i + 1 < digit.length)
{
if (digit[i] == digit[i + 1])
{
count[i]++;
i++;
}
}
}
for (int i = 0; i < digit.length; i++)
{
if (count[i] > 0)
{
System.out.println(digit[i] + " appears " + count[i]+" time(s)");
}
}
}