I am learning about Recursions, and I haven't fully grasped it yet. So here I am trying to do an assignment on recursion but I'm stuck.
In this assignment, I am supposed to ask the user to input phrases, and the program determines whether it's a palindrome or not. We are supposed to accomplish this task using recursions.
This is the section with the recursion, and I can't quite figure out how to tackle it, as when I run it, I get no error, but it always comes up as false.
I'm using a ArrayList to keep all the user input.
Here's the code I've got right now
//instance variables
private boolean det;
private String input;
private String inputHelp;
//constructor
public RecursivePalindrome(String i)
{
det = false;
input = i;
inputHelp = "";
}
//determines if the method is a palindrome or not using recursions
public boolean palindrome(String b)
{
if(inputHelp.length() == 0)
{
det = true;
}
if(inputHelp.substring( 0 , 1 ).equals(inputHelp.substring( inputHelp.length() )))
{
inputHelp = inputHelp.substring( 1, inputHelp.length());
palindrome(inputHelp);
}
else
{
det = false;
}
return det;
}
There are three mistakes. First, note the substring documentation: second parameter is the end index "exlusive". Secondly, you need to use the result of the recursive call. And finally (as pointed out correctly by ajb in the comments), you should account for palindromes with odd letter count (first condition):
if (inputHelp.length() <= 1)
{
det = true;
}
else if (inputHelp.substring(0, 1)
.equals(inputHelp.substring(inputHelp.length() - 1)))
{
inputHelp = inputHelp.substring( 1, inputHelp.length() - 1);
det = palindrome(inputHelp);
}
else
{
det = false;
}
Also, you can make it a bit more readable:
public boolean palindrome(String b)
{
if (b.length() <= 1)
{
return true;
}
if (b.substring(0, 1)
.equals(b.substring(b.length() - 1)))
{
return palindrome(b.substring(1, b.length() - 1));
}
return false;
}
Further improvements can be made - lines still seem to long, especially the second condition (left as an exercise for the reader ;)).
As far as I can tell you are never setting inputHelp to anything other than an empty string, and the string b which is passed in to your method is not used anywhere.
So the method will never call back on to itself, and even if it did the value passed in would not be used for anything, rendering the recursion useless.
Related
I have four methods that check whether or not a given grid location is next to an occupied location (value of 1). The grid is assumed to wrap around, ie, if in a 50x50 grid[0][1] is the given location and grid[49][1] is occupied, the method should return true/ My checkNorth and checkEast method are working fine, but I get an ArrayIndexOutofBoundsException: -1 error for either the south or west methods every time I run the program. I checked my math and I think it should work - am I using the modulo incorrectly, or am I missing something else?
EDIT: Clarified the wrapping criterion, word use correction.
boolean checkWest(int indexA, int indexB)
{
if (indexA-1 > 0)
{
if (grid[indexA-1][indexB] == 1)
{
return true;
}
}
if (indexA-1 < 0)
{
if (grid[(indexA-1)%width][indexB] == 1)
{return true;}
else return false;
}
return false;
}
I see a couple problems. First, Java arrays are zero-indexed, which means that the first element is at index 0. So it's okay to check grid[indexA-1][indexB] when indexA-1 is equal to 0. Second, you're not properly handling when indexA equals 0. Here is my implementation. I also simplified the logic a bit.
boolean checkWest(int indexA, int indexB)
{
if (indexA > 0)
return grid[indexA - 1][indexB] == 1;
else
return grid[width + indexA - 2][indexB] == 1;
}
EDIT: I'm pretty sure I butchered the math with the second return statement. It should be right now...
I am currently making a text adventure game in Java, but I have come across a problem:
I need the value of a String variable to change each time the value of a particular int variable changes.
I want the program to perform this task (then continue where it left off) each time the value of an int variable changes:
if (enemyposition == 1) {
enemyp = "in front of you";
}
else if (enemyposition == 2) {
enemyp = "behind you";
}
else if (enemyposition == 3) {
enemyp = "to your left";
}
else if (enemyposition == 4) {
enemyp = "to your right";
}
else {
enemyp = "WOAH";
}
Thanks! :D
You could make the code much shorter using an array.
String[] message = {"WOAH", // 0
"in front of you", // 1
"behind you", // 2
"to your left", // 3
"to your right"}; // 4
enemyp = (enemyposition > 0 && enemyposition < 5) ? message[enemyposition] :
message[0];
The question you're asking sounds like it might be answerable by creating a class to hold the enemyposition integer. Add a "setter" method to your class to set the integer. You can write your setter method so that when the integer is set, it also sets up a string. Then write a "getter" method to retrieve the string. That's one common way of making sure two variables change together.
public class EnemyPosition {
private int enemyposition;
private String enemyp;
public void setPosition(int n) {
enemyposition = n;
enemyp = [adapt your code to set this based on the position]
}
public String getEnemyp() {
return enemyp;
}
}
I'm sure there are a lot of details missing, but you get the idea. Then instead of int enemyposition in the rest of your code, use EnemyPosition enemyposition = new EnemyPosition(), and use the setPosition method instead of assigning to it.
That's not the only solution (an array or Map that maps integers to strings may be good enough), but it's one OOP way to do things.
Still working on my sudoku solver, I have once again run into some trouble. I have gotten the sudoku solver to work, however whenever I attempt to solve a really "hard" sudoku board, my solver tells me there are no possible solutions, due to a stack overflow error. And yes, I know for a fact that these boards DO have a solution.
I am using the brute force algorithm -- I start at square one (or [0][0] if you prefer) and insert the first legal value. I then do a recursive call to the next square, and so on. If my function has not gone through the entire board, and finds there are no possible legal values, it moves to the previous square and attempts to increment the value there. If that fails, it moves further back. If it ends up at square one with no possible solutions, it exits.
I admit my code is not pretty and probably quite inefftective, but please keep in mind that I am a first year student trying to do my best. I don't mind comments on how to effectivize my code though :)
For squares without a final predefined number, here's the solver function:
public void fillRemainderOfBoard(Square sender){
try {
while(true){
if(currentPos > boardDimension){
if(previous != null){
this.setNumrep(-1);
this.setCurrentPos(1);
previous.setCurrentPos(previous.getCurrentPos()+1);
previous.fillRemainderOfBoard(this);
return;
} else if(sender == this){
this.setCurrentPos(1);
} else {
break;
}
}
if((thisBox.hasNumber(currentPos)) || (thisRow.hasNumber(currentPos)) || (thisColumn.hasNumber(currentPos))){
currentPos++;
} else {
this.setNumrep(currentPos);
currentPos++;
break;
}
}
if(this != last){
next.setNumrep(-1);
next.fillRemainderOfBoard(this);
} else {
return;
}
} catch (StackOverflowError e){
return;
}
}
In my code, the numrep value is the value that the square represents on the board. The currentPos variable is a counter that starts at 1 and increments until it reaches a legal value for the square to represent.
For squares with a predefined number, here's the same function:
public void fillRemainderOfBoard(Square sender){
if((sender.equals(this) || sender.equals(previous)) && this != last){
System.out.println(next);
next.fillRemainderOfBoard(this);
} else if (sender.equals(next) && this != first) {
previous.fillRemainderOfBoard(this);
} else {
System.out.println("No possible solutions for this board.");
}
}
Now, my problem is, like I said, that the function DOES solve sudokus very well. Easy ones. The tricky sudokus, like those with many predefined numbers and only a single solution, just makes my program go into a stack overflow and tell me there are no possible solutions. I assume this indicates I am missing something in the terms of memory management, or the program duplicating objects which I call in my recursive functions, but I do not know how to fix them.
Any help is greatly appreciated! Feel free to pick on my code too; I'm still learning (oh, aren't we always?).
___________________EDIT________________
Thanks to Piotr who came up with the good idea of backtracking, I have rewritten my code. However, I still cannot get it to solve any sudoku at all. Even with an empty board, it gets to square number 39, and then returns false all the way back. Here is my current code:
public boolean fillInnRemainingOfBoard(Square sender){
if(this instanceof SquarePredef && next != null){
return next.fillInnRemainingOfBoard(this);
} else if (this instanceof SquarePredef && next == null){
return true;
}
if(this instanceof SquareNoPredef){
currentPos = 1;
if(next != null){
System.out.println(this.index);
for(; currentPos <= boardDimension; currentPos++){
if((thisBox.hasNumber(currentPos)) || (thisRow.hasNumber(currentPos)) || (thisColumn.hasNumber(currentPos))){
continue;
} else {
System.out.println("Box has " + currentPos + "? " + thisBox.hasNumber(currentPos));
this.setNumrep(currentPos);
System.out.println("Got here, square " + index + " i: " + numrep);
}
if(next != null && next.fillInnRemainingOfBoard(this)){
System.out.println("Returnerer true");
return true;
} else {
}
}
}
if(next == null){
return true;
}
}
System.out.println("Returning false. Square: " + index + " currentPos: " + currentPos);
return false;
}
I had to complicate things a bit because I needed to check whether the current object is the last. Hence the additional if tests. Oh, and the reason I am using boardDimension is because this sudoku solver will solve any sudoku -- not just those 9 by 9 sudokus :)
Can you spot my error? Any help is appreciated!
So your problem lies here:
previous.fillRemainderOfBoard(this);
and here
next.fillRemainderOfBoard(this);
Basically you have too many function calls on the stack because you are going forward and backward multiple times. You are not really returning from any call before answer is found (or you get StackOverflowError :)). Instead of increasing stack size by using recursive function try to think how to solve problem using a loop (pretty much always loop is better than recursive solution performance wise).
Ok so you can do something like this (pseudo code):
boolean fillRemainderOfBoard(Square sender){
if (num_defined_on_start) {
return next.fillRemainderOfBoard(this);
} else {
for (i = 1; i < 9; ++i) {
if (setting i a legal_move)
this.setCurrentPos(i);
else
continue;
if (next.fillRemainderOfBoard(this))
return true;
}
return false;
}
The stack size will be ~81.
I just got a task asking me to do repeated addition from 1 to 21, as follows :
1,4,6,9,11,14,16,19,21
and get the total.
I tried this code but it returned to be a +2 addition, and it even bypass the prerequisite of bil<=21
public class test
{
public static void main(String[]args)
{
int bil=1;
long total=0;
boolean mult = true;
for(bil=1; bil<=21;bil++)
{
if(mult=true)
{
bil+=1;
mult=false;
}
else if(mult=false)
{
bil+=2;
mult=true;
}
System.out.println(bil);
total=total+bil;
}
System.out.println("----+");
System.out.println(total);
}
}
(if it's TL;DR)
Basically the request is 1+4+6+9+11+14+16+19+21=?
I can't seem to get these code to work, please help me?
EDIT : Thanks guys I got it now :D
You need boolean mult = false; so that the first time the loop runs, bil is incremented by 3 and not 2.
First, you are not comparing your boolean with ==. Therefore, every time the for() loop executes, the first block will be the one that enters since mult = true will always store true in mult... and then qualify that if() block to run.
If this assignment wasn't intentional, then you need to change it to == and also put some logic in your loop to toggle mult appropriately.
Basically when it runs through the first loop it only adds one because of the state of the boolean but also there should be an == operator to check instead of just an =
Try this:
for (bil = 1; bil < 21; bil++) {
if (bil % 2 == 0) { // If bil is divisible by 2, then add 2
bil += 2;
continue;
}
bil += 3;
}
I'm trying to make a method that will tell me weather or not it is true or false that a number is prime. here's the code:
class prime
{
public static boolean prime (int a, int b)
{
if (a == 0)
{
return false;
}
else if (a%(b-1) == 0)
{
return false;
}
else if (b>1)
{
prime (a, b-1) ;
}
else
{
return true;
}
}
public static void main (String[] arg)
{
System.out.println (prime (45, 45)) ;
}
}
when i try to compile this i get this error message:
prime.java:23: missing return statement
}
^
1 error
I could be misinterpreting what the error message is saying but it seems to me that there isn't a missing return statement since i have a return statement for every possible set of conditions. if a is 0 then it returns false, if it isn't then it checks to see if a is dividable by b if it is then it returns if not then if b is greater than 1 it starts over again. if b isn't greater than 1 it also returns.
Also it seems a bit messy to have to
make this method take two ints that
are the same int.
What is wrong with my syntax/ why am i getting the error message? Is there a way to make it so that the method that i use in main only has to take one int (perhaps another method splits that int into two clones that are then passed to public static boolean primeproper?
or is there a more effective way of
going about this that i'm missing
entirely?
In your prime function, there are four possible code paths, one of which doesn't return anything. That is what the error message is complaining about. You need to replace:
prime (a, b-1) ;
with:
return prime (a, b-1) ;
in the else if (b>1) case.
Having said that, this is actually not a good way to calculate if a number is prime. The problem is that every recursive call allocates a stack frame and you'll get into serious stack overflow problems if you're trying to work out whether 99,999,999 is a prime number?
Recursion is a very nice tool for a certain subset of problems but you need to be aware of the stack depth. As to more efficient solutions, the are many tests you can carry out to determine a number is not prime, then only check the others with a brute force test.
One thing you should be aware of is to check divisibility against smaller numbers first since this will reduce your search scope quicker. And don't use divide where multiply will do, multiplication is typically faster (though not always).
And some possibly sneaky tricks along the lines of:
every number other than 2 that ends in 2, 4, 6, 8 or 0 is non-prime.
every number other than 5 that ends in 5 is non-prime.
Those two rules alone will reduce your search space by 60%. Assuming you get your test number as a string, it's a simple matter to test the last digit of that string even before converting to an integral type.
There are some more complex rules for divisibility checks. If you take a multiple of 9 and sum all the digits to get a new number, then do it again to that number, then keep going until you have a single digit, you'll find that it's always 9.
That will give you another 10% reduction in search space albeit with a more time-expensive check. Keep in mind that these checks are only advantageous for really large numbers. The advantages are not so great for, say, 32-bit integers since a pre-calculated bitmap would be much more efficient there (see below).
For a simplistic start, I would use the following iterative solution:
public static boolean prime (int num) {
int t = 2;
while (t * t <= num) {
if ((num % t) == 0) {
return false;
}
t++;
}
return true;
}
If you want real speed in your code, don't calculate it each time at all. Calculate it once to create a bit array (one of the sieve methods will do it) of all primes across the range you're interested in, then simply check your values against that bit array.
If you don't even want the cost of calculating the array every time your program starts, do it once and save the bit array to a disk file, loading it as your program starts.
I actually have a list of the first 100 million primes in a file and it's easier and faster for me to use grep to find if a number is prime, than to run some code to calculate it :-)
As to why your algorithm (fixed with a return statement) insists that 7 is not prime, it will insist that every number is non-prime (haven't checked with negative numbers, I'm pretty sure they would cause some serious problems - your first check should probably be if (a < 1) ...).
Let's examine what happens when you call prime(3,3).
First time through, it hits the third condition so calls prime(3,2).
Then it hits the second condition since 3 % (2-1) == 0 is true (N % 1 is always 0).
So it returns false. This could probably be fixed by changing the third condition to else if (b>2) although I haven't tested that thoroughly since I don't think a recursive solution is a good idea anyway.
The following complete code snippet will do what you need although I appreciate your curiosity in wanting to know what you did wrong. That's the mark of someone who's actually going to end up a good code cutter.
public class prime
{
public static boolean isPrime (int num) {
int t = 2;
while (t * t <= num) {
if ((num % t) == 0) {
return false;
}
t++;
}
return true;
}
public static void main (String[] arg)
{
System.out.println (isPrime (7)) ;
}
}
You seem to be under the impression that because the recursion will eventually find a base-case which will hit a return statement, then that return will bubble up through all of the recursive calls. That's not true. Each recursive call must pass out the result like this:
return prime(a, b - 1);
If b is larger than 1, your function won't return anything.
May it be return prime (a, b-1) ; ?
To improve efficiency, think more about your conditions. Do you really need test every factor from 2 to N? Is there a different stopping point that will help tests of prime numbers complete more quickly?
To make a better API, consider making the recursive method private, with a public entry point that helps bootstrap the process. For example:
public static boolean prime(int n) {
return recurse(n, n);
}
private static boolean recurse(int a, int b) {
...
}
Making a method private means that it can't be called from another class. It's effectively invisible to users of the class. The intent here is to hide the "ugly" extra parameter by providing a public helper method.
Think about the factors of some composite numbers. 10 factors to 5×2. 12 factors to 6×2. 14 factors to 7×2. Now think about 25. 25 factors to 5×5. What about 9? Do you see a pattern? By the way, if this isn't homework, please let me know. Being this didactic is hard on me.
In answer to why 7 isn't working, pretend you're the computer and work through your logic. Here's what you wrote.
class prime
{
public static boolean prime (int a, int b)
{
if (a == 0)
{
return false;
}
else if (a%(b-1) == 0)
{
return false;
}
else if (b>1)
{
// Have to add the return statement
// here as others have pointed out!
return prime(a, b-1);
}
else
{
return true;
}
}
public static void main (String[] arg)
{
System.out.println (prime (45, 45)) ;
}
}
So let's start with 7.
if(7 == 0) // not true, don't enter this block
else if(7 % 6 == 0) // not true
else if(7 > 1) // true, call prime(7, 6)
if(7 == 0) // not true, don't enter this block
else if(7 % 5 == 0) // not true
else if(6 > 1) // true, call prime(7, 5)
if(7 == 0) // not true, don't enter this block
else if(7 % 4 == 0) // not true
else if(5 > 1) // true, call prime(7, 4)
... keep going down to calling prime(7, 2)
if(7 == 0) // not true, don't enter this block
else if(7 % 1 == 0) true, return false
When you get down to calling prime(n, 2), it will always return false because you have a logic error.
Your recursive method must return a value so it can unroll.
public static boolean prime (int a, int b)
{
if (a == 0)
{
return false;
}
else if (a%(b-1) == 0)
{
return false;
}
else if (b>1)
{
return prime (a, b-1) ;
}
else
{
return true;
}
}
I might write it a different way, but that is the reason that you are not able to compile the code.
I think the original question was answered already - you need to insert return in the body of else if (b>1) - I just wanted to point out that your code still will crash when given 1 as the value for b, throwing an ArithmeticException since a%(b-1) will be evaluated to a%0, causing a division by zero.
You can avoid this by making the first if-statement if (a == 0 || b == 1) {}
This won't improve the way the program finds primes, it just makes sure there is one less way to crash it.
Similar to #paxdiblo's answer, but slightly more efficient.
public static boolean isPrime(int num) {
if (num <= 1 || (num & 1) == 0) return false;
for (int t = 3; t * t <= num; t += 2)
if (num % t == 0)
return false;
return true;
}
Once it is determined that the number is not even, all the even numbers can be skipped. This will halve the numbers which need to be checked.