I want to change the first method to a while and for loop. I have added the code below. Is this correct?
public String extractWordFour(String text){
if(text.length()==0 || text.charAt(0) == ''){
return "";
} else {
return text.charAt(0) + extractWordFour(text.substring(1));
}
}
public String extractWordFour(String text){
int i=0;
while (i<=text.length){
return text.charAt(0) + extractWordFour(text.substring(i));
i++;
}
}
public String extractWordFour(String text){
for(int i=0;i<=text.length();i++){
return text.charAt(0) + text.substring(1);
}
}
I'm not going to answer this question because I think its a h.w. assignment but I'm putting it in an answer since I can't fit this in a comment, but I'm assuming you want to convert a recursive solution into a while or for loop solution.
Your while solution is wrong first of all because you are mixing recursion and while together. You should not be calling the function inside your while loop!
public String extractWordFour(String text){
int i=0;
while (i<=text.length){
return text.charAt(0) + extractWordFour(text.substring(i));
i++;
}
}
This one can't finish because you are returning it before its even looped more than once.
public String extractWordFour(String text){
for(int i=0;i<=text.length();i++){
return text.charAt(0) + text.substring(1);
}
}
Anyways hope that helps. The best thing to do would be to fully understand what the first function does, write it down and then think about how to make it do the exact same thing with a while or a for loop.
For a start, you can't have String.charAt(0) == '' because '' isn't a valid character, unlike "" for an empty String which is valid.
Your second method doesn't work because it should be text.length() instead of text.length which is the method when you're calling it on an array, as well as the i++ being unreachable because of the recursion. And failing that, the method signature claims it returns a String, but there is no return statement.
Your third method does have a return statement, but it still wouldn't work because it'll just return on the first iteration and therefore only give you the first 2 characters (and in fact your compiler won't even allow it because it won't realise this).
Aside from all these issues, if the method name of extractWordFour is an accurate representation of what they should do, none of them will because the logic makes no sense. I suggest you start by thinking about that: How can you tell when one word ends by examining the String, and what does your program need to know to remove everything before the fourth word, and everything after it?
Related
i need to get a string and rearrange it with recursion by getting char and by that char i have to move that char everywhere on the string to the end
like "Hello world!" ,'l' => "Heo word!lll"
i have problems understading the recursion way of thinking
so i started with this:
public static String ChToLast (String str, char ch){
if(str.indexOf(ch)== -1){
return str;
}else{
if(str.indexOf(0) == ch){
return str;
}
}
thank you for your help :)
Recursion is the practise of reusing your method inside itself. In this case, I will provide a solution to explain what happens:
public static String chrToLast(String str, char ch) {
//This if statement details the end condition
if(str.length() < 1) {
return "";
}
String newString = str.substring(1); //Create new string without first character
if(str.indexOf(ch) == 0) { //This happens when your character is found
return chrToLast(newString, ch) + ch;
} else { //This happens with all other characters
return str.charAt(0) + chrToLast(newString, ch);
}
}
If you execute:
chrToLast("Hello, World!", 'l')
This will result in the desired result: Heo, Word!lll
Process
In general, this method works by checking which character is currently the first in the given string, and then deciding what to do. If the first character is the same as the one your looking for (l), it will then remove that character from the string and use chrToLast on that new string. But, it also adds the character it found to the end of the result by using + ch. It continues to do this until there are no more characters left, which is what the end condition is for.
The end condition
The end condition returns an empty string "" because that is what is called the base case of the algorithm. You can think of a recursive algorithm as something solving a problem by calling itself a number of times. By calling themselves, recursive algorithms move towards a base. In this particular case, it does that by subtracting one character off the string each time the method is executed. Once there are no characters left, it reaches the base case which is "", where the string is finally empty and no characters can be subtracted anymore. (Hence it returns nothing as it's final state)
I hope this answers your question. It's important to understand this concept, as it is very powerful. Try to study the code and comment if something's not clear.
Something that can also help is by executing this code in an IDE and using the debugger to walk through its execution. You can then see for yourself what the flow of the program is, and see the value of the variables in play.
If you use recursion, it will be pretty expensive call for the result you are expecting. Lot of movement of String or charArray elements, eitherway you do. I don't see its a wiser choice. I would do it this way, it will be of space complexity O(2n) & performance complexity O(n).
public class Solve {
public static void main(String[] args) {
System.out.println(ChToLast("Hello world!", 'l'));
}
public static String ChToLast(String str, char ch) {
char[] chars = str.toCharArray();
char[] modChars = new char[chars.length];
int i = 0;
for(char element : chars){
if(ch != element){
modChars[i++] = element;
}
}
Arrays.fill(modChars, i, chars.length , ch);
return new String(modChars);
}
}
If you use while loop and write a method to check if that string means perfect statement then that may work for you
Here you would need some help of NLP concept to check everytime if arranged chars are making any statement or are grammatically correct.
This will help
This question already has answers here:
"Missing return statement" within if / for / while
(7 answers)
Closed 8 years ago.
I'm writing a method to find the upper case letters in a given string. I have this
public static String FindUpperCase (String x){
for (int i = x.length(); i>=0; i--){
if (Character.isUpperCase(x.charAt(i))){
return x.substring(i); }
}
But I'm getting an error thats telling me I must return a string. When I look up on the API what substring does it tells me that it returns a string that is a subset of the other string...which means I am returning a string, right? I was told that it was because I am returning a string within the loop and that's not the same thing but I'm a little confused by what this means because isn't the loop in the method? Does anyone know what I'm doing wrong or how I can fix this?
No, you're not always returning a string. What if the input is entirely lower case?
Basically, you need a return statement (or throw an exception) after the for loop, to handle the situation where you get to the end of it. Even in cases that you can reason that you'll never actually get to the end of the loop, the Java compiler follows strict rules for reachability, as specified in section 14.21 of the JLS. So even if your return statement were unconditional and we know that length() always returns a non-negative value, this still wouldn't compile:
public static String broken(String input) {
// *We* know that we'll always go into the body of the loop...
for (int x = input.length(); x >= 0; x--) {
return input;
}
// The end of the method is still reachable from the compiler's standpoint
}
The end of a non-void method can't be reachable - you must either throw an exception or return a value.
Also note that your initial value should be x.length() - 1 or x.charAt(i) will throw an exception. You should also change your method name to follow Java naming conventions.
Oh, and currently you're not returning "the upper case letters" - you're returning "everything from the last upper case character onwards" which is entirely different.
You are returning subjected to a condition, so if the condition is never true you are not returning. Try instead.
public static String FindUpperCase (String x){
for (int i = x.length() - 1; i>=0; i--){
if (Character.isUpperCase(x.charAt(i))){
return x.substring(i); }
return "";
}
Also Java is indexes start at 0, so your for sentence starts at x.length() - 1 (last position) or you will get StringIndexOutOfBoundsException
Consider the case when there's no uppercase in the given string, in that case, the function won't return anything.
So just after your for loop, you can return an empty string to make the function declaration valid.
Because you return string only if Character.isUpperCase(x.charAt(i)) is true. You have to return for example empty string if it is false.
public static String FindUpperCase (String x){
for (int i = x.length(); i>=0; i--){
if (Character.isUpperCase(x.charAt(i))){
return x.substring(i); }
}
return "";
}
Your problem is, that you are returning a string dependend on an if statement. You have to return a string or null in every possible case. Just place a return null or return "" at the last line of the function for a quick and dirty solution. Better would be to think what you want to return if no uppercase character is found.
Here is my method:
//usedLetters method to check if user's guess has already been guessed
private boolean usedLetters(char used[], char alphabet) throws IOException
{
for(int x=0; x<used.length; x++){
if(alphabet == used[x])
{
return true;
}
else
{
used[dataSize] = alphabet;
return false;
}
}
}//End of usedLetters method
IT checks to see if the alphabet that the user entered in an another method has already been guessed. If it has already been guessed, it returns true, and if has not been already guessed, it adds the alphabet into used, and returns false. But the error says that there are no return statements...I am not familiar with methods in general, so I am confused. Any help would be appreciated!
What if used.length==0? Then the for-loop is never entered.
Therefore you need a return statement after the loop.
What if the for is never entered? i.e. used.length == 0 (used is an empty array). In this case - nothing will be returned.
The compiler forbids a flow that can terminate without returning the value, and that's why it shows the error.
Also note, I believe even after fixing this issue - the program will yield a wrong result, it will only check the first element of used, without advancing to the next one.
You should move the return false; to just before the last }. Otherwise it will return in the first iteration of the loop.
/usedLetters method to check if user's guess has already been guessed
private boolean usedLetters(char used[], char alphabet) throws IOException
{
for(int x=0; x
if(alphabet == used[x])
{
return true;
}
else
{
used[dataSize] = alphabet;
return false;
}
}
}//End of usedLetters method
There should be return statement after for loop, currently there is no return statement that's why you are getting error.
As you have written your code, the method will always return on the first iteration of the cycle, while I doubt this is what you want.
I believe that you should return false outside the for. I am not sure what does to "guess an alphabet" mean but I think this is what you are trying to do.
Yep, all the above are correct. You would be better off defining the return variable at the top, setting it to values wherever you need to within the method body, breaking out of the 'for' loop and returning it once at the end.
I have researched this topic for a while, but without much success. I did find the StringBuilder and it works wonders, but that's as far as I got. Here is how I got my hangman program to work like it should:
if(strGuess.equalsIgnoreCase("t")){
mainword.replace(0,1,"T");
gletters.append('T');
}
else if(strGuess.equalsIgnoreCase("e")){
mainword.replace(1,2,"E");
gletters.append('E');
}
else if(strGuess.equalsIgnoreCase("c")){
mainword.replace(2,3,"C");
gletters.append('C');
}
else if(strGuess.equalsIgnoreCase("h")){
mainword.replace(3,4,"H");
gletters.append('H');
}
else if(strGuess.equalsIgnoreCase("n")){
mainword.replace(4,5,"N");
gletters.append('N');
}
else if(strGuess.equalsIgnoreCase("o")){
mainword.replace(5,6,"O");
mainword.replace(7,8,"O");
gletters.append('O');
}
else if(strGuess.equalsIgnoreCase("l")){
mainword.replace(6,7,"L");
gletters.append('L');
}
else if(strGuess.equalsIgnoreCase("g")){
mainword.replace(8,9,"G");
gletters.append('G');
}
else if(strGuess.equalsIgnoreCase("y")){
mainword.replace(9,10,"Y");
gletters.append('Y');
}
else{
JOptionPane.showMessageDialog(null, "Sorry, that wasn't in the word!");
errors++;
gletters.append(strGuess.toUpperCase());
}
SetMain = mainword.toString();
GuessedLetters = gletters.toString();
WordLabel.setText(SetMain);
GuessedLabel.setText(GuessedLetters);
GuessText.setText(null);
GuessText.requestFocusInWindow();
However, I can't do this for EVERY letter for EVERY word, so is there a simple and efficient way to do this? What I want is to have a loop of some sort so that I would only have to use it once for whatever word. So the word could be technology (like it is above) or apple or pickles or christmas or hello or whatever.
I have tried using a for loop, and I feel the answer lies in that. And if someone could explain the charAt() method and how/where to use it, that'd be good. The closest I got to being more efficient is:
for(i = 0; i < GuessWord.length(); i++) {
if (GuessWord.charAt(i) == guess2) {
mainword.replace(i,i,strGuess.toUpperCase());
}
So if you could use that as a basis and go off of it, like fix it? Or tell me something I haven't thought of.
It's a good question. There's clearly repeated code, so how do you replace all that with something reusable. Actually, you can dispense with all of your code.
That whole code block can be replaced by just one line (that works for every word)!
String word = "TECHNOLOGY"; // This is the word the user must guess
mainword = word.replaceAll("[^" + gletters + "]", "_");
This uses replaceAll() with a regex that means "any letter not already guessed" and replaces it with a underscore character "_". Note that Strings are immutable, and the replaceAll() method returns the modified String - it doesn't modify the String called on.
Here's some test code to show it in action:
public static void main(String[] args) {
String word = "TECHNOLOGY"; // what the user must guess
StringBuilder gletters = new StringBuilder("GOTCHA"); // letters guessed
String mainword = word.replaceAll("[^" + gletters + "]", "_");
System.out.println(mainword);
}
Output:
T_CH_O_OG_
As an exercise, the code block below intends to recursively go through a string and remove all the of the "x" characters. It does that, but I would like to keep track of the newStr without passing it as a parameter in the method. Is there anyway to move it into the method body?
Thanks!
public static String deathToX(String str, String newStr) {
//look for x char
if(str.substring(0, 1).equals("x")) {
//do nothing
} else {
//add non-x char to newStr
newStr += str.charAt(0);
}
if(str.length() == 1) {
return newStr;
}
return deathToX(str.substring(1), newStr);
}
public static void main(String[] args) {
System.out.println("Return: " + deathToX("xnoxmore", ""));
}
Well, you could change the code to:
public static String deathToX(String str)
{
// Termination case
if (str.length() == 0)
{
return str;
}
// Work out whether or not we want the first character
String prefix = str.startsWith("x") ? "" : str.substring(0, 1);
// Let the recursive call handle the rest of the string, and return
// the prefix (empty string or the first character) followed by the
// x-stripped remainder.
return prefix + deathToX(str.substring(1));
}
Is that the sort of thing you were thinking of?
Of course, this is a horribly inefficient way of doing string manipulation, but I assume you're more interested in the recursive nature of things.
I would like to keep track of the newStr without passing it as a parameter in the method.
Why? Passing the intermediary result into the function is often required in functional-style recursive programming. What I do is make a function that handles the bulk of the work and accepts the accumulator, and make a wrapper function that calls the previous one with the required starter value:
private static String deathToX0(String str, String newStr) {
// the original implementation
}
public static String deathToX(String str) {
return deathToX(str, "");
}
As an aside, you might not want to use a String for the intermediate result because of the copying involved. A StringBuilder would be faster.
The short answer is yes... with recursion typically on the way down the tree you work out the bit at each level in this case blank or the current character. So the return statement should call itself recursively then at the bottom of the tree the answer you wanted is reconstructed by adding together the sections at each level.
public static String deathToX(String str){
if (!str.isEmpty()){
return (str.substring(0, 1).equals("x") ? "" : str.substring(0, 1)) + deathToX(str.substring(1));
}else{
return "";
}
}
public static void main(String[] args){
System.out.println("Return: " + deathToX("xnoxmore"));
}
In the sample above I used the shorthand if format to put it all on one line but you could expand it out. You should be able to see that the recursive function recurses on the return statement and I put in a special case for the last level. If you were to split it and put this levels answer in a local variable e.g. tmp then you would use:
return tmp + deathToX(str.substring(1));
Remember recursion means that the current execution is only paused until the lower ones finish so you can happily store info to recover on your way back up. Hope this helps :)
public class solution {
// Return the changed string
public static String removeX(String input){
if(input.equals("") || input.equals("x"))
return "";
String returnStr="";
removeX(input.substring(1));
for(int i=0;i<input.length();i++)
{
if(input.charAt(i)=='x')
continue;
else
returnStr+=input.charAt(i);
}
return returnStr;
}
}
This is my approach. This code goes to the end of the string, if it gets X as last string, it returns ""(nothing), then it checks the whole substring for "x", if its present in the string, it will continue, else it will append rest character to that string and it goes on.
Finally returns the updated string.!
Hope this helps..!! well, this is my first contribution here :)