Indenting an output with recursion - java

I am trying to use recursion to print out two lines of text each and with an indent every time there's recursion (example in javadoc below). I know using (numCalls + 1) will allow it to increase the indent each time but I'm not sure how to actually put it together so does what it is asking for.
public class Practice1 {
/**
* Prints 2 lines of text for each recursive call, indicating call number
* (a value >= 1, and <= value of numCalls, as illustrated below. Each
* level of recursion should be indicated by indenting the input line by
* r spaces. For example, if numCalls is 3, the method should print:
* call 1
* call 2
* call 3
* back 3
* back 2
* back 1
* #param r the level of method calls
* #param numCalls the number of intended levels
*/
public static void stairSteps(int r, int numCalls) {
if (r == 0) {
System.out.println("Done");
} else {
System.out.println("call " + r);
System.out.println("back " + r);
r--;
numCalls++;
stairSteps(r, numCalls);
}
}

public static void stairSteps(int totalLevels, int indent) {
stairSteps(1, totalLevels, indent);
System.out.println("Done");
}
private static void stairSteps(int level, int totalLevels, int indent) {
if (level <= totalLevels) {
int offs = indent * (level - 1);
System.out.println(" ".repeat(offs) + "call " + level);
stairSteps(level + 1, totalLevels, indent);
System.out.println(" ".repeat(offs) + "back " + level);
}
}
Output:
stairSteps(3, 2);
call 1
call 2
call 3
back 3
back 2
back 1
Done

Related

Brute Force the Frog Jumping Game

The last variation of the Frog Jumping is shown at the end of the video.
In short, you have n number of lily pads in a line and one frog on
each one.
In the last variation (the one I want to brute force), the second
first and second last lily pads do not have a frog. Your goal is to
get all frogs to the same lily pad. Each frog can jump right or left
based on the number of frogs on its lily pad, but can't jump on a
empty lily pad.
(pad with 1 frog moves 1 spot, pad with n frogs moves only n spots)
Example of a solution for n=12: (there are no solutions below 12)
[1,0,1,1,1,1,1,1,1,1,0,1] - Starting formation of frogs. (counting
frogs from 0. to 11.) [1,0,1,0,2,1,1,1,1,1,0,1] - Frog 3. jumped
right [1,0,1,0,2,1,2,0,1,1,0,1] - Frog 7. jumped left
[1,0,1,0,4,1,0,0,1,1,0,1] - Frogs 6. jumped left
[5,0,1,0,0,1,0,0,1,1,0,1] - Frogs 4. jumped left
[0,0,1,0,0,6,0,0,1,1,0,1] - Frogs 0. jumped right
[0,0,1,0,0,0,0,0,1,1,0,7] - Frogs 5. jumped right
[0,0,1,0,0,0,0,0,0,2,0,7] - Frogs 8. jumped right
[0,0,1,0,0,0,0,0,0,0,0,9] - Frogs 9. jumped right
[0,0,10,0,0,0,0,0,0,0,0,0] - Frogs 11. jumped left- solved
I want to find solutions for n frogs, if the solution exists. I know by hand that 12,14,15,16,17,18,19,20 have at least one solution and that 1-11 and 13 do not have a solution.
I tried writing a piece of code that would run through all combinations to find a solution for n lily pads.
EDIT: The code works now, thanks to OleV.V., also added logging.
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
// # Brute Force # Brute Force # Brute Force # Brute Force # Brute Force # //
public class Frogger {
/**
* PUBLIC STATIC GLOBAL VARIABLES - Modify these as you wish.
*
* Time Data: Levels < 20 ~ around couple seconds
* Level = 20 ~ around a minute
* Level = 21 ~ around a quarter of an hour
* Level = 22 ~ around a sixth of a minute
* Level = 23 ~ around half an hour
* Level = 24 ~ around a minute
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
public static int Level = 12;
public static boolean LogSolution = true;
public static boolean LogAll = false;
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// used for logging
private static Deque<Jump> solution = new ArrayDeque<>(Level);
private static double time;
public static void main(String[] args) {
// log the time
time = System.currentTimeMillis();
// build the world & start jumping
run(Level);
}
public static void run(int n) {
// create the world
int[] world = new int[n];
for (int i = 0; i < n; i++) {
world[i] = 1;
}
world[1] = 0;
world[n-2] = 0;
// start jumping
if (Level > 11 && Level != 13) jump(world);
else System.out.println("Unsolvable");
}
//////////////////////////////////////////////////////
public static void jump(int[] world) {
for (int i = 0; i < world.length; i++) {
if (world[i] != 0) { // pad has a frog
// check if it is solved at current pad
if (world[i] == Level - 2) {
System.out.println("SOLUTION: " + Arrays.toString(world));
System.out.println(solution);
System.out.println("\n" + (System.currentTimeMillis() - time) / 1000 + " seconds");
System.exit(0);
}
// roll-back var
int temp = 0;
// attempts to make a RIGHT jump
if (world[i] + i < world.length) { // right jump is in bound
if (world[i + world[i]] != 0) { // can't jump on empty pad
temp = world[i];
// jump RIGHT
world[i + world[i]] += world[i];
world[i] = 0;
solution.push(new Jump(temp, i, i + temp)); // log the solution step 1/2
if (LogSolution) if (LogAll) System.out.println( "J: " + Arrays.toString(world)); // log the jump
// continue jumping
jump(world);
// roll-back right jump
world[i] = temp;
world[i + world[i]] -= world[i];
if (LogAll) System.out.println("R: " + Arrays.toString(world)); // log the rollback
if (LogSolution) solution.pop(); // log the solution step 2/2
}
}
// attempts to make a LEFT jump
if (i - world[i] >= 0) { // left jump is in bound
if (world[i - world[i]] != 0) { // can't jump on empty pad
temp = world[i];
// jump LEFT
world[i - world[i]] += world[i];
world[i] = 0;
if (LogSolution) solution.push(new Jump(temp, i, i - temp)); // log the solution step 1/2
if (LogAll) System.out.println("J:" + Arrays.toString(world)); // log the jump
// continue jumping
jump(world);
// roll-back left jump
world[i] = temp;
world[i - world[i]] -= world[i];
if (LogAll) System.out.println("R: " + Arrays.toString(world)); // log the rollback
if (LogSolution) solution.pop(); // log the solution step 2/2
}
}
}
}
}
}
Side note: This problem was mathematically solved for all solvable n (all n > 11, other than 13, have a solution, reachable by a generalized method). This piece of code is just me attempting to do some recursion in java.
Glad you got it to work. I don’t think you need my code now, but I will give at the bottom of this answer in case.
First, how does one log a solution? I guess you’re thinking that knowing that the end result was [0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0] is not that interesting; we’d like to know how it was obtained. I will present two ways.
The easier way is store each step as it is tried and then delete it when backtracking. Then when you get to the solution, you have also stored the steps that lead to it. Use a stack or similar:
private static Deque<Jump> solution = new ArrayDeque<>(Level);
(java.util.ArrayDeque is the recommended class for both stacks and queues; for a stack ArrayList is another option.) Now in your code, where it says log the jump do
solution.push(new Jump(temp, i, i + temp));
At log the rollback do
solution.pop();
Use a simple auxiliary class Jump that could for instance look like this:
public class Jump {
int count;
int from;
int to;
public Jump(int count, int from, int to) {
this.count = count;
this.from = from;
this.to = to;
}
#Override
public String toString() {
return "" + count + " frog/s jump from " + from + " to " + to;
}
}
When I tried it in my solution, one search took 20 % longer. I’d say it’s acceptable. If you are very concerned about performance, only log on your way out from having found the solution. This will require you to return a boolean to indicate success rather than using System.exit() for stopping the search. Now your recursive call becomes:
if (jump(world)) {
solution.push(new Jump(temp, i, i + temp));
return true;
}
You get the elements in your solution stack in the opposite order than before, I expect you to figure that out. Also instead of System.exit(0); do return true;. At the bottom of the method, return false. I have not measured performance impact, but I expect it to be minute compared to logging nothing. Now you can get output like:
1 frog/s jump from 3 to 4
1 frog/s jump from 7 to 6
2 frog/s jump from 6 to 4
4 frog/s jump from 4 to 0
5 frog/s jump from 0 to 5
6 frog/s jump from 5 to 11
1 frog/s jump from 8 to 9
2 frog/s jump from 9 to 11
9 frog/s jump from 11 to 2
Finally here’s how I did, just for the sake of completeness. I haven’t spotted any interesting differences from your code.
public static void jump(int[] world) {
for (int fromIndex = 0; fromIndex < world.length; fromIndex++) { // index of pad to jump from
// any frog/s here?
int frogsJumping = world[fromIndex];
if (frogsJumping > 0) {
// try to jump left; frogsJumping frogs jump frogsJumping places
int targetIndex = fromIndex - frogsJumping;
if (targetIndex >= 0 && world[targetIndex] > 0) { // must not jump to empty pad
performJump(fromIndex, targetIndex, world, frogsJumping);
}
// try a right jump
targetIndex = fromIndex + frogsJumping;
if (targetIndex < world.length && world[targetIndex] > 0) {
performJump(fromIndex, targetIndex, world, frogsJumping);
}
}
}
}
private static void performJump(int fromIndex, int toIndex, int[] world, int frogsJumping) {
solution.push(new Jump(frogsJumping, fromIndex, toIndex));
world[fromIndex] = 0;
world[toIndex] += frogsJumping;
if (world[toIndex] == noOfFrogs) {
System.out.println("Solved: " + Arrays.toString(world));
System.exit(0);
}
jump(world);
// backtrack
world[toIndex] -= frogsJumping;
world[fromIndex] = frogsJumping;
solution.pop();
}

Recursion - explanation how the code works (drawing)

i write this code and i try to understand all activities performed (recursive).
Can anyone help me with this draw me up a tree in memory of what happens?
public static String row(int n) {
if (n == 1)
return "1";
else
return row(n - 1) + " " + n;
}
public static String triangle(int a, int b) {
if (a == b)
return row(b);
else
return row(a) + "\n" + triangle(a + 1, b);
}
}
thank's
Your row method:
public static String row(int n) {
if (n == 1) {
return "1";
} else {
return row(n - 1) + " " + n;
}
}
Returns a String containing all the numbers from 1 - n separated by spaces. E.g.row(4) will return a string "1 2 3 4".
Your triangle method prints one row for each row of a triangle.
public static String triangle(int a, int b) {
if (a == b) {
return row(b);
} else {
return row(a) + "\n" + triangle(a + 1, b);
}
}
creates one row of a triangle for each step of row from a up to b.
e.g. triangle(4,6) will print:
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
How the code works
The row method, if given the value 1 will return "1". Any other value will result in a string equivalent to row(n-1) followed by n so essentially it will return 1 2 3 ... n.
The triangle method returns a string which attempts to draw a triangle with numbers. Thus triangle(4,6) returns row(4) + triangle(5,6) which returns row(5) + triangle(6,6) which will returns row(6). Thus the final result will be:
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6

Counting recursive calls

is there a mathematical formula to calculate how many times the recursive function is called for the following without having to check with my complier
How many times will mystery2 be called recursively when invoked with the call
mystery2(1000)?
public void mystery2(int n)
{
if (n <= 1)
System.out.print(n);
else
{
mystery2(n / 2);
System.out.print(", " + n);
}
}
1, 3, 7, 15, 31, 62, 125, 250, 500, 1000 = 10 times
There is no "formula", but there is a general technique for solving recurrences. Here you have the recurrence
N(x) = 1 + N(floor(x / 2))
with the base case
N(1) = 1
The definition of N(x) is "the number of times mystery2 is called if its initial argument is x".
Recurrences are solved by "tricks" that are learned like integration formulas or else fancy math like generating functions. Sometimes approximations are the best you can do. In your case, if we do away with the floor operator (or assume x is a power of 2), then it's pretty clear that
N(x) = 1 + log_2(x)
We can verify this. if x is 1, we have N(x) = 1 + 0 = 1. For x = 2, we have N(x) = 1 + 1 = 2 and so forth... For x = 1024, it's N(x) = 1 + 10 = 11.
With the floor operator, the exact answer is more complicated, depending on the number of odd factors of x, but the formula above will always be close.
Use ceil from log2(n)
ceil(log2(1000)) = ceil(9.966) = 10
Another option is to pass the count into your method;
public void mystery2(int n) {
mystery2(n, 1);
}
public void mystery2(int n, int count) {
if (n <= 1)
System.out.print(n);
else
{
mystery2(n / 2, count+1);
System.out.print(", " + n + ":count=" + count);
}
}
Edit: I thought of a better way to do it. You can return the count as you go like this.
public static void mystery2(int n) {
System.out.print("\ncount = " + mystery2(n, 1));
}
public static int mystery2(int n, int count) {
if (n <= 1) {
System.out.print(n);
return count;
}
System.out.print(n + ", ");
return mystery2(n / 2, count + 1);
}
Use a static variable, or a global
public void mystery2(int n)
{
static count = 0;
count++;
system.out.print("We have called this " + count + "times before...");
if (n <= 1)
System.out.print(n);
else
{
mystery2(n / 2);
System.out.print(", " + n);
}
}
outside the method make a variable like mysteryCnt = 0; (must initialize to 0) then inside the ELSE block increment it after the method, mysteryCnt ++; that might work.
else{
mystery2(n / 2);
mysteryCnt ++;
System.out.println(", " + n);
}
Jonny Z has the right idea but you cannot initialize the variable inside the method or it will never increment past 1; the way he did it, it will set to 0 then increment to 1 every time you call the method.

Sum values in binary tree of integers weighted by depth

Here is my reference tree:
3
/ \
5 2
/ / \
1 4 6
Here is the expected output of the recursive method:
(1*3) + (2 * (5 + 2)) + (3 * (1 + 4 + 6)) = 50
...and here is the code I have thus far:
public int depthSum()
{
int depth = 1;
return depthSum(overallRoot, depth);
}
public int depthSum(IntTreeNode someNode, int someDepth)
{
if(someNode == null)
{
return 0;
}
else
{
return someDepth * someNode.data + //some recursion
}
}
I get that I have to likely call myself and increment someDepth, but I can't seem to get this right. Any ideas?
Presumably you mean:
return someDepth * someNode.data +
depthSum(someNode.left, someDepth+1) +
depthSum(someNode.right, someDepth+1);

What's going on inside of this recursive function?

I have this recursive factorial function:
public class Driver{
public static void main (String args[])
{
System.out.println(factorial(5));
}
private static int factorial(int n)
{
int product;
if (n <= 2){ product = n; return 2;}
else{
product = n * factorial(n-1);
System.out.println("current product =" + product);
System.out.println("product = " + n + " * factorial(" + (n-1) + ")");
}
return product;
}
}
It prints the following:
current product =6
product = 3 * factorial(2)
current product =24
product = 4 * factorial(3)
current product =120
product = 5 * factorial(4)
120
I'm trying to figure out what the heck is going on here. I don't understand how it starts printing for n = 2. And where did current product = 6 come from? Thanks!
n==2 is your base case, so the first function to get past the below line is the one where n-1 == 2 or n == 3. This is because your output is performed after the recursive call, so it prints the deepest call first (thanks Patricia Shanahan) . If you want it to print from big to small, move your println lines above the line which calls factorial recursively.
product = n * factorial(n-1);
Also,
if (n <= 2){ product = n; return 2;}
This is wrong for so many reasons..
It should be
if (n <= 1){ return 1;}
If you are having trouble understanding this, remember that each call of factorial is independent of other calls.

Categories

Resources