public class Main {
public static int count = 0;
public static void main(String[] args) {
String str = "AAAA";
System.out.println(delete1(str));;
}
private static int delete1(String str) {
if (str.length() > 1) {
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i-1) == str.charAt(i)) {
count++;
str = str.substring(i, str.length());
delete1(str);
}
}
}
return count;
}
}
count should come as 3 in this case...but coming as 4
For loop inside recursive method does not have break statement. put break; statement after delete1(str); statement will work.
delete1(str);
break;
while using recursive you should know where to break the loop and how functional flow happens in java.
in your case for all sub strings of length more than 2 will call delete method more than once. that's why you got output as 4.
There are multiple things wrong with your code:
You have the count on class-level and also let your method return this count.
You continue your loop after your recursive call
Not really wrong, but your if(str.length() > 1) check is redundant since your loop is already looping in the range [1, length), so the loop wouldn't start anyway if the length is smaller than or equal to 1.
Keeping the things above in mind, you could change it to this:
class Main {
public static void main(String[] args){
String str = "AAAA"; // Expected output: 3
countChars(str);
System.out.println(count);
}
private static int count = 0;
private static void countChars(String str){
int length = str.length();
for(int i = 1; i < length; i++){
if(str.charAt(i-1) == str.charAt(i)){
count++;
String substr = str.substring(i, length);
countChars(substr);
break;
}
}
}
}
Which puts the count at 3 in the end as you expected.
Try it online.
I'm still not entirely sure what you are trying to accomplish however. For example, what would the expected output be for AAAABABBAB or ABAAAAABBABA? Also, it would be better if the count isn't a static class-level field so it can more easily be re-used.
Related
I'm a beginner with java and one concept is rather unclear to me. I need to create a method that creates a new string by replicating another string. For example, if the String1 is "java" and it is specified that it needs to be repeated 4 times and each of them needs to be separated with a comma, the new string would look like this: java, java, java, java
However, the method should not print it, but only create a new string that is then printed in the main program. This is a problem for me, because I have trouble understanding, how can I use a loop to create something without printing it. I think that the following code would print it correctly:
public static void replicate(String str, int times) {
for (int i = 0; i < times; i++) {
System.out.print(str);
if (i < times -1) {
System.out.print(", ");
}
}
}
How could I transform it so that I could use the method to create a new string without printing it? I am assuming this is something super simple, but I just don't know at all how to do this, because every guide just uses examples of printing in these kinds of situations.
This is much better with Collections and join
import java.util.*;
public class Main
{
public static void main(String[] args)
{
String newstr=String.join(",", Collections.nCopies(3, "java"));
System.out.println(newstr);
}
}
Working fiddle-https://repl.it/repls/OfficialInvolvedObject
This is easy to do using the StringBuilder class, which can be used like this:
public static String replicate(String str, int times) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < times; i++) {
builder.append(str);
if (i < times - 1) {
builder.append(", ");
}
}
return builder.toString();
}
The following code should be useful for academic purposes in which you cannot use all of Java's libraries. You want to use a variable to store the repeated text and then return that variable to the main method for it to be printed. For non academic purposes or in cases when efficiency is a priority the java.lang.StringBuilder object should be used.
public static String replicate(String str, int times) {
String newString = "";
for (int i = 0; i < times; i++) {
newString = newString + str;
if(i<times-1){
newString = newString + ", ";
}
}
return newString;
}
One option is to use a StringBuilder, as exemplified by Emily's answer. Since the same delimiter is used each time another option is to use java.util.StringJoiner. Here's an example:
public static String replicate(String str, int times) {
StringJoiner joiner = new StringJoiner(", ");
for (int i = 0; i < times; i++) {
joiner.add(str);
}
return joiner.toString();
}
I am assuming this is something super simple
You are right. While the other answers show various helper classes, you can do it with re-assigning a single String variable already:
public static String replicate(String str, int times) {
String result="";
for (int i = 0; i < times; i++) {
result += str; //System.out.print(str);
if (i < times -1) {
result += ", "; //System.out.print(", ");
}
}
return result;
}
Or, if you do not worry about having to provide 0 copies:
public static String replicate(String str, int times) {
String result=str; // one copy, without comma
for (int i = 1; i < times; i++) {
result += ", " + str; // all the other copies have their commas
}
return result;
}
This latter "trick" can be used with StringBuilder too of course:
public static String replicate(String str, int times) {
StringBuilder result = new StringBuilder(str);
for (int i = 1; i < times; i++) {
result.append(", ");
result.append(str);
}
return result.toString();
}
Btw, it may be worth mentioning what there story about StringBuilder is: when Java sees something=string1+string2, internally it writes StringBuilder temp=new StringBuilder(string1); temp.append(string2); something=temp.toString() (of course it is an unnamed, internal variable, not "temp"). So a brand new StringBuilder object is created, appended, converted back to a brand new String and thrown away every time. That is why the suggested method is to have one, dedicated StringBuilder, use it many times, and get the result from it only once, at the end.
Good morning all,
Today is my first time trying to make a recursion method. Just when I thought it would work I got the error; missing return statement. This confuses me because it literally has a return value ( the total string from the Stringbuilder ) after n < 1
This is what I got:
import java.util.Scanner;
public class P5_4MethodRepeatString {
public void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("Enter a string followed by the times you want
it repeated:");
String input = sc.nextLine();
int count = sc.nextInt();
String total = repeat(input, count);
System.out.println(total);
}
public static String repeat(String str, int n) {
StringBuilder full = new StringBuilder();
if(n < 1) {return full.toString();}
repeat(str, n - 1);
for(int i = 0; i < n; i++){
full.append(str);
}
}
}
if(n < 1) {return full.toString();} but if n >= 1 you don't return anything. It should be return repeat(str, n - 1); but then you need to move the for... part
The immediate cause of your problem is that not all conditional flows in your repeat() method have a return value. But I am not sure if even making that change would result in working code. Consider the following refactor:
public void repeat(StringBuilder result, String str, int n) {
if (n == 0) return;
result.append(str);
repeat(result, str, n - 1);
return;
}
Here we are passing in a StringBuilder object which we want to contain our repeated string results. We also pass the string to be repeated, and the number of remaining turns. The base case occurs where there are no more turns, in which case we simply return from the recursive method. Otherwise, we add one copy of the string and make a recursive call.
Your original recursive attempt had the following for loop:
for (int i=0; i < n; i++) {
full.append(str);
}
This does not look recursive, and looping to repeatedly add the string defeats the point of doing recursion (though I would probably use a loop in real life if I had to do this).
This code is for counting words in the input. It works except when no words are in the input - it returns 1 and not 0. What is wrong here?
import java.util.Scanner;
public class Exercise12 {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
System.out.println("Input, Stop by #");
String input = kb.nextLine();
while (! input.equals("#")) {
wordCount(input);
input = kb.nextLine();
}
} //main
public static void wordCount(String countSpace) {
int count = 1;
for (int i =0; i < countSpace.length(); i++ ) {
if ((countSpace.charAt(i)) == ' ') {
count++;
}
}
System.out.println(count);
}
} // class Exercise12
To get everything right you should trim() your String to remove leading and trailing whitespaces. Then split the String at whitespace and count all non empty Strings. Empty Strings are caused by consecutive whitespaces.
Use Java 8:
public static void wordCount(String countSpace) {
System.out.println(Arrays.stream(countSpace.trim().split(" ")).filter(word->!word.isEmpty()).count());
}
You could use the split function like this:
public static void wordCount(String countSpace) {
String[] words = countSpace.split(" ");
int count = words.length;
System.out.println(count);
}
EDIT:
As #Jérôme suggested below, I added the trim function and a check for the empty input and now it works correctly. I also changed the string in the split function to the "\s+" regex, as #Aleks G suggested. Thak you for your corrections. See the updated code below:
public static void wordCount(String countSpace) {
String[] words = countSpace.trim().split("\\s+");
int count = 0;
if (!(words[0].equals(""))){
count = words.length;
}
System.out.println(count);
}
TL;DR: Use StringTokenizer:
public static void wordCount(String input) {
int count = new java.util.StringTokenizer(input).countTokens();
System.out.println(count);
}
Long explanation:
Your code is almost correct, however you initialise your count to 1. Then you increment it for every space character that you find. At the end of the input you do not have a space, thus you do not increment the count for the last word - and this compensates you starting with 1 and not 0. Yet, in case of empty input, you start with 1 and there's nothing to read - therefore you end up with a wrong value.
The first fix is simple: change the initialisation to be int count = 0:
public static void wordCount(String countSpace) {
int count = 0;
for (int i =0; i < countSpace.length(); i++ ) {
if ((countSpace.charAt(i)) == ' ') {
count++;
}
}
System.out.println(count);
}
The next problem is that you're not counting words, but rather word separators. What if there are two consecutive spaces between two words? Further, what happens if you encounter end of line or end of file? Your code will break on those.
Ideally, you should use a tokenizer to count your words, but as a minimum, you should count how may times you switched from a space/line-end to an alphanumeric character. Here's an example of using a Tokenizer:
public static void wordCount(String input) {
int count = new java.util.StringTokenizer(input).countTokens();
System.out.println(count);
}
You need to handle the case of empty inputs separately. In addition you should keep in mind that an input might contain two consecutive spaces or spaces at the beginning/end of the line, which shouldn't count for words.
With these special cases, the code would look like this:
public static void wordCount(String in){
boolean isspace = true;
int count = 0;
for(int i = 0; i < in.length(); i++)
{
//increment count on start of a word
if(isspace && in.charAt(i) != ' ')
{
count++;
isspace = false;
}
//reset isspace flag on end of a word
else if(!isspace && in.charAt(i) == ' ')
isspace = true;
}
System.out.println(count);
}
This code makes sure that words are only counted when they are actually encountered and repeated spaces get ignored.
I am trying to create a Mastermind game in which colors are numbers [] and one number can never repeat itself in the String. The string should be made of 4 characters. I cannot figure out why my code keeps on printing strings with repeated characters.
import java.util.Random;
import java.util.Scanner;
public class Question1
{
public static void main(String[] args)
{
String toGuess="";
while(!IsValidNumber(toGuess));
{
for(int i=0; i<4; i++)
{
Random rando= new Random();
int rd=rando.nextInt(9);
toGuess=toGuess+rd;
}
}
System.out.println(toGuess);
}
public static boolean IsValidNumber(String s) // boolean
{
boolean noRepetition = true;
for(int i = 0; i < s.length(); i++)
{
for(int j = 0; j < i; j++)
{
if(i == j)
{
continue;
}
else if(s.charAt(i) == s.charAt(j))
{
noRepetition = false;
return false;
}
}
}
return noRepetition;
}
}
The boolean IsValidNumber never operates, I tried to print simple check words at different levels of it, and nothing ever prints but the String.
Thanks in advance, cheers
You've got a stray semicolon after the while() declaration, which causes the loop to immediately end. Consequently, your for loop constructs a number, and whatever number it constructs is immediately printed.
Consider the following instead:
public static void main(String[] args)
{
String toGuess="";
do { // Always try to generate at least one number.
toGuess = ""; //Reset each time we loop.
for(int i=0; i<4; i++) {
Random rando= new Random();
int rd=rando.nextInt(9);
toGuess=toGuess+rd;
}
} while(!IsValidNumber(toGuess));
System.out.println(toGuess);
}
That might work better.
Basically, while (exp); is equivalent to while(exp) {} or an empty while loop. Only put a semicolon after your while(exp) when using the do...while construct I illustrate here.
I am using a for loop to print the backwards alphabet in uppercase but I would like to know how to do the same thing with a while loop, which I am not very good with.
String alphabet = "abcdefghijklmnopqstuvwxyz";
int x = 0;
for(x = alphabet.length() - 1; x > -1; x--) {
System.out.print(alphabet.charAt(x));
System.out.print(alphabet.toUpperCase());
}
I also need to terminate it when it reaches A. think it's something like this, but I don't know how to make it loop backwards. I'd really appreciate your help!
while(alphabet.length() < 26) {
System.out.print(alphabet.charAt(x));
System.out.print(alphabet.toUpperCase());
if(x == A) {
break;
}
}
for (initialization; condition; increment) {
}
is same as:
{
initialization;
while(condition) {
// body
increment;
}
}
The outer block creates a block scope for the initialized parameter, that we get in a for loop also. But, if you are declaring your for-loop variable outside the loop, then you can omit that outer block.
Now you can map your for loop to the while loop.
There is a much simpler way to reverse a string in Java.
public class StringReversalExample {
public static void main(String[] args) {
String alphabet = "abcdefghijklmnopqstuvwxyz";
String reversedString = new StringBuilder(alphabet).reverse().toString();
System.out.println(reversedString);
}
}
Try this:
public static void main(String[] args) {
char[] alphabet = "abcdefghijklmnopqstuvwxyz".toCharArray();
int index = alphabet.length - 1;
while (index >= 0) {
System.out.println(alphabet[index--]);
}
}
This is a most efficient solution with minimal memory overhead.
x = alphabet.length() - 1;
while( x > -1 )
{
System.out.print( alphabet.charAt( x ));
System.out.print( alphabet.toUpperCase() );
x--;
}