I want to count the number of recursion steps and stop the recursion when a certain limit is reached.
Actually I am dealing with the Tower of Hanoi problem and I want to limit the number of slides that are performed to solve the problem. Here is my solution:
class HanoiNK{
public static void main(String args[]){
int n = 4;
int k = 5;
try{
slide(k, n, 'A', 'B', 'C');
}catch(Exception e){
System.out.println(e);
}
}
public static void slide(int counter, int height, char source,
char buffer, char destination) throws Exception{
if(counter > 0){
if(height == 1){
System.out.println("move "+ height +" from " +
source + " to " + destination);
}else{
counter--;
slide(counter, height - 1, source, destination, buffer);
System.out.println("move "+ hoehe +" from " +
source + " to " + destination);
counter--;
slide(counter, height - 1, buffer, source, destination);
}
}else{
throw new Exception("stop here");
}
}
}
Here is the live example: http://ideone.com/xeN4x
My problem is that I get
move 1 from A to B
move 2 from A to C
move 1 from B to C
move 3 from A to B
move 1 from C to A
move 2 from C to B
java.lang.Exception: stop
as output. But 5 and not 6 slides should be performed. Any ideas?
The problem is you are testing if counter is greater than or equal to one, but then decrementing it by two.
counter--;
// ...
counter--;
Here counter can go negative. You need to check for that.
Since you want to count the number of moves and not the recursion depth, you need to store the number of moves that were made in each step. Something like this:
public static int slide(int counter, int hoehe, char quelle, char ablage, char ziel)
throws Exception{
if (hoehe == 1) {
System.out.println("move "+ hoehe +" from " +
quelle + " to " + ziel);
if (--counter == 0) throw new Exception("hier stoppen");
} else {
counter = slide(counter, hoehe - 1, quelle, ziel, ablage);
System.out.println("move "+ hoehe +" from " +
quelle + " to " + ziel);
if (--counter == 0) throw new Exception("hier stoppen");
counter = slide(counter, hoehe - 1, ablage, quelle, ziel);
}
return counter;
}
Then, you obtain the expected result:
move 1 from A to B
move 2 from A to C
move 1 from B to C
move 3 from A to B
move 1 from C to A
java.lang.Exception: hier stoppen
Here is an sample method that will be recursively get called counter times
public void callMe(int counter){
if(counter == 1 ){
return;
}else{
callMe(--counter);
}
}
in your code there are counter--; twice so it won't met condition in many case
You have to test for your counter at every decrements like this:
public static void slide(int counter, int hoehe, char quelle,
char ablage, char ziel) throws Exception{
if(hoehe == 1){
System.out.println("move "+ hoehe +" from " +
quelle + " to " + ziel);
}else{
if (--counter == 0) throw new Exception("hier stoppen");
slide(counter, hoehe - 1, quelle, ziel, ablage);
System.out.println("move "+ hoehe +" from " +
quelle + " to " + ziel);
if (--counter == 0) throw new Exception("hier stoppen");
slide(counter, hoehe - 1, ablage, quelle, ziel);
}
}
Related
I have been learning java for a few months now at school and we started recursions. Recursion where you just print stuff, void, are pretty simple, but I can't quite grasp ones that have returns. I just wrote a simple code that checked if something is less more than 50. I could've use num >= 50, but this is just a proof of concept. I will just return true if it is over 50 and false if less than 50. For some reason, it always returns false, even if it ran true before. How can I fix this?
public static boolean greaterthanfifty(int i, int counter) {
if(i > 0 && counter == 50) {
System.out.println("First if: i: " + i + " counter: " + counter);
return true;
} else if(i <= 0 && counter == 50) {
System.out.println("2nd if: i: " + i + " counter: " + counter);
return false;
} else {
greaterthanfifty(i - 1, counter + 1);
System.out.println("i: " + i + " counter: " + counter);
return false;
}
}
Try this:
public static boolean greaterthanfifty(int i, int counter) {
if(i > 0 && counter == 50) {
System.out.println("First if: i: " + i + " counter: " + counter);
return true;
} else if(i <= 0 && counter == 50) {
System.out.println("2nd if: i: " + i + " counter: " + counter);
return false;
} else {
System.out.println("i: " + i + " counter: " + counter);
return greaterthanfifty(i - 1, counter + 1);;
}
}
because:
else {
greaterthanfifty(i - 1, counter + 1);
System.out.println("i: " + i + " counter: " + counter);
return false;
}
here you are going to return anyway false.
I can end the first. I am trying to make it on odd turns player goes and even turns CPU goes.
public static void main(String[] args) {
Random random = new Random();
Scanner keyboard = new Scanner(System.in);
String mage = "mage";
System.out.println("mage, warrior, assassin, ranger?");
String input = keyboard.nextLine();
int playerAttackDice = random.nextInt(20) + 1;
int cpuAttackDice = random.nextInt(20) + 1;
int playerDefenseDice = random.nextInt(5) + 1;
int cpuDefenseDice = random.nextInt(5) + 1;
int turn = 1;
while(mage.equalsIgnoreCase(input)) {
Mage player = new Mage();
Warrior CPU = new Warrior();
System.out.println("You have selected: mage");
System.out.println("Your Attack Power is: " + player.getMageAttack());
System.out.println("Your Defense is: " + player.getMageDefense());
System.out.println("Your Health is: " + player.getMageHealth());
System.out.println("Your enemy is a: warrior");
System.out.println("Enemy Attack Power is: " + CPU.getMageAttack());
System.out.println("Enemy Defense is: " + CPU.getMageDefense());
System.out.println("Enemy Health is: " + CPU.getMageHealth());
System.out.println();
This is where the turn begins. I was trying to set it to make it player goes on odd numbers in the when the CPU goes. Am I even approaching this in the right way? Any help would be very much appreciated.
while(player.mageHealth != 0) {
System.out.println("Your health is: " + player.mageHealth);
for(turn = 1; turn % 1 ==0; turn++) {
if(turn % 1==0) {
System.out.println("Your dice roll is:" + playerAttackDice);
int playerDamage = playerAttackDice + player.mageAttack;
int cpuDefense = cpuDefenseDice + CPU.mageDefense;
System.out.println(playerDamage);
System.out.println(cpuDefense);
System.out.println("CPU health is: " + (CPU.mageHealth + cpuDefense - playerDamage ));
return;
}
}
turn++;
for(turn = 2; turn % 2 ==0; turn++) {
while(turn % 2==0) {
System.out.println("CPU dice roll is:" + cpuAttackDice);
System.out.println("Your dice roll is:" + playerDefenseDice);
int cpuDamage = playerDefenseDice + player.mageAttack;
int playerDefense = cpuAttackDice + CPU.mageHealth;
System.out.println(cpuDamage);
System.out.println(playerDefense);
}
}
}
System.out.println("end loop");
break;
}
}
If you want Player and CPU to play their move one after another - just put their actions one after another with no inner loops and complex conditions around
while (!game.isOver()) {
player.makeMove();
cpu.makeMove();
}
or having your code there
while(player.mageHealth > 0) { // game over condition
//player move
System.out.println("Your health is: " + player.mageHealth);
System.out.println("Your dice roll is:" + playerAttackDice);
int playerDamage = playerAttackDice + player.mageAttack;
int cpuDefense = cpuDefenseDice + CPU.mageDefense;
System.out.println(playerDamage);
System.out.println(cpuDefense);
System.out.println("CPU health is: " + (CPU.mageHealth + cpuDefense - playerDamage ));
//cpu move
System.out.println("CPU dice roll is:" + cpuAttackDice);
System.out.println("Your dice roll is:" + playerDefenseDice);
int cpuDamage = playerDefenseDice + player.mageAttack;
int playerDefense = cpuAttackDice + CPU.mageHealth;
System.out.println(cpuDamage);
System.out.println(playerDefense);
player.mageHealth = player.mageHealth + playerDefence - cpuDamage;
}
Im learning java with "programmingbydoing" and i have a problem with Nim game, everything works fine apart from one thing, which is that both:
"System.out.print(n1 + ", choose a pile: ");"
and
"System.out.print(n2 + ", choose a pile: ");"
is out printed twice after the first time.
Here is code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Player one, enter your name: ");
String n1 = input.nextLine();
System.out.print("Player two, enter your name: ");
String n2 = input.nextLine();
int a = 3;
int b = 4;
int c = 5;
int count = 1;
System.out.println("A: "+a+" B: "+b+" C: "+c);
nim_loop:while(a > 0 || b > 0 || c > 0) {
while(count % 2 != 0 ) {
System.out.print(n1+", choose a pile: ");
String first = input.nextLine();
if (first.contains("a") || first.contains("A")) {
System.out.print("How many to remove from pile " + first + "? ");
int second = input.nextInt();
count = count + 1;
a = a - second;
System.out.println("A: " + a + " B: " + b + " C: " + c);
if(a <= 0 && b <= 0 && c <= 0){
break nim_loop;
}
}
else if (first.contains("b") || first.contains("B")) {
System.out.print("How many to remove from pile " + first + "? ");
int second = input.nextInt();
count = count + 1;
b = b - second;
System.out.println("A: " + a + " B: " + b + " C: " + c);
if(a <= 0 && b <= 0 && c <= 0){
break nim_loop;
}
}
else if (first.contains("c") || first.contains("C")) {
System.out.print("How many to remove from pile " + first + "? ");
int second = input.nextInt();
count = count + 1;
c = c - second;
System.out.println("A: " + a + " B: " + b + " C: " + c);
if(a <= 0 && b <= 0 && c <= 0){
break nim_loop;
}
}
}
while(count % 2 == 0) {
System.out.print(n2 + ", choose a pile: ");
String third = input.nextLine();
if (third.contains("a") || third.contains("A")) {
System.out.print("How many to remove from pile " + third + "? ");
int fourth = input.nextInt();
count = count + 1;
a = a - fourth;
System.out.println("A: " + a + " B: " + b + " C: " + c);
} else if (third.contains("b") || third.contains("B")) {
System.out.print("How many to remove from pile " + third + "? ");
int fourth = input.nextInt();
count = count + 1;
b = b - fourth;
System.out.println("A: " + a + " B: " + b + " C: " + c);
} else if (third.contains("c") || third.contains("C")) {
System.out.print("How many to remove from pile " + third + "? ");
int fourth = input.nextInt();
count = count + 1;
c = c - fourth;
System.out.println("A: " + a + " B: " + b + " C: " + c);
}
}
}
if (count % 2 != 0) {
System.out.println("Game ended, Player " + n1 + " is a winner.");
} else if (count % 2 == 0){
System.out.println("Game ended, Player " + n2 + " is a winner.");
}
}
}
And here are the pictures of what happens when i run it:
When the first if condition in first inner loop is true and when you get the user input by using nextInt() it only reads the int value and does not consume the last new line character i,e \n. So the subsequent call to nextLine() will be skipped i,e the nextLine() call in second inner while loop will be skipped without any value but System.out.print(n2 + ", choose a pile: "); will be printed as it is before nextLine() call and control goes back to outer while loop.
Now the count value is 2 so first inner while condition will be false and control goes to second inner while loop. And again it prints b, choose a pile:. Hope this clears your question
Workaround is fire a blank nextLine() call after every nextInt() or use nextLine() inside if condition and parse the user input using Integer.parseInt(String) method.
Example code :
if (first.contains("a") || first.contains("A")) {
System.out.print("How many to remove from pile " + first + "? ");
int second = input.nextInt();
input.nextLine(); // firing an blank nextLine call
count = count + 1;
a = a - second;
System.out.println("A: " + a + " B: " + b + " C: " + c);
if(a <= 0 && b <= 0 && c <= 0){
break nim_loop;
}
For more information - Scanner is skipping nextLine() after using next(), nextInt() or other nextFoo() methods
The output of the code is 1,1, 2,2 3,3, 4,4, instead of 1, 2, 3, 4. I tried a lot of different placements for the a variable to make it work, but this is the closest I have gotten it. Am I just misunderstanding something fundamental about recursion?
import java.util.Scanner;
public class TowerOfHanoi {
public static int a = 1;
public static void main(String[] args) {
TowerOfHanoi towerOfHanoi = new TowerOfHanoi();
System.out.println("Enter number of disks: ");
Scanner scan = new Scanner(System.in);
int disks = scan.nextInt();
towerOfHanoi.solve(disks, "1", "2", "3");
scan.close();
}
public void solve(int n, String start, String mid, String end){
if(n == 1){
System.out.println(a + " : "+ start + " to " + end);
a++;
} else {
solve(n-1, start, end, mid);
System.out.println(a + " : " + start + " to " + end);
solve(n-1, mid, start, end);
}
}
}
Output:
Enter number of disks:
3
1 : 1 to 3
2 : 1 to 2
2 : 3 to 2
3 : 1 to 3
3 : 2 to 1
4 : 2 to 3
4 : 1 to 3
The sequence of steps looks right to me, but you forgot to increment a in the else clause in solve(...).
Solve should look something like this:
public void solve(int n, String start, String mid, String end) {
if (n == 1) {
System.out.println(a + " : "+ start + " to " + end);
a++;
} else {
solve(n-1, start, end, mid);
System.out.println(a + " : " + start + " to " + end);
a++;
solve(n-1, mid, start, end);
}
}
a should be incremented after each println, not just the first.
I'm trying to build an AVL tree in Java, but I'm having trouble with updating heights after the rotations. Here is the code I'm having trouble with.
public void checkHeights(Node<T> u) {
if (u == nil) return;
checkHeights(u.left);
checkHeights(u.right);
System.out.println(u.h);
if (height(u) != 1 + Math.max(height(u.left), height(u.right)))
throw new RuntimeException("Check heights shows incorrect heights");
int dif = height(u.left) - height(u.right);
if (dif < -1 || dif > 1)
throw new RuntimeException("Check heights found height difference of " + dif);
}
/**
* Fix up
* #param u
*/
public void fixup(Node<T> u) {
while (u != nil) {
int dif = height(u.left) - height(u.right);
if(debug)System.out.println("Node dif at " + u.x + " is: " + dif);
if (dif > 1) {
if(debug)System.out.println("u.left is larger");
if(height(u.left.left) - height(u.left.right) < 0) {
if(debug)System.out.println("u.left dif is: " + (height(u.left.left) - height(u.left.right)));
rotateLeft(u.left);
}
rotateRight(u);
} else if (dif < -1) {
if(debug)System.out.println("u.right is larger");
if(height(u.right.left) - height(u.right.right) > 0) {
if(debug)System.out.println("u.right dif is: " + (height(u.right.left) - height(u.right.right)));
rotateRight(u.right);
}
rotateLeft(u);
}
if(debug) System.out.println("Height of " + u.x + " is " + height(u));
u = u.parent;
}
}
public void rotateLeft(Node<T> u) {
super.rotateLeft(u);
u.h = Math.max(height(u.left), height(u.right)) + 1;
u.parent.h = Math.max(height(u.parent.left), height(u.parent.right)) + 1;
if(debug)System.out.println("After left rotation, " + u.x + " has height " + u.h + " and " + u.parent.x + " has height " + u.parent.h);
}
public void rotateRight(Node<T> u) {
super.rotateRight(u);
u.h = Math.max(height(u.left), height(u.right)) + 1;
u.parent.h = Math.max(height(u.parent.left), height(u.parent.right)) + 1;
if(debug)System.out.println("After right rotation, " + u.x + " has height " + u.h + " and " + u.parent.x + " has height " + u.parent.h);
}
I've done a bunch of unit tests, and I keep getting checkHeights throwing exceptions. I'm almost positive that what's going on is the when a rotation occurs at a depth greater than 2, the heights aren't updated recursively up the tree. For example, if I add values from 0 to 10 in, the first left rotation occurs no problem and the values get their right heights, but when I try to rotate lower down, the parent nodes aren't accurately update to their new heights, causing the exceptions to be thrown.
Any help would be greatly appreciated