Factorial Recursion, answer doesn't make sense on paper? - java

So I was on codingbat doing recursion excercises and I ran into this
public int factorial(int n) {
if (n == 1) {
return 1;
}
return n * factorial(n-1);
}
I don't understand how this works on paper. as 1 returns 1 thats fine, 2 returns 2, thats fine, 3 returns 6 thats fine, but then factorial(4) returns 24? factorial(5) returns 120?
It doesn't make sense because it is doing it from the last answer of n I assume but not minusing 1? But passes all the tests. So it does 6*4 = 24, rather than 4x(n-1) which wouldn't equal 24? Help?

For any factorial(n), it is computed as n x (n-1) x (n-2) x ... x 1
So for factorial(4) that will be 4 x 3 x 2 x 1 = 24
Recursion is mostly introduced using factorial as an example, so to visualize it will look like
fact(4) = 4 x fact(3)
= 4 x 3 x fact(2)
= 4 x 3 x 2 x fact(1)
= 4 x 3 x 2 x 1 = 24
The recursion repeats until it hits the "anchor" which is the base case of 1

When you're trying to understand recursion, it's good to picture a stack. Every time we're calling return n * factorial(n - 1) we are pushing a value down the stack so we can retrieve it after we're done computing the factorial(n - 1) call. And so on so forth.
factorial(5)
= 5 * factorial(4)
= 5 * 4 * factorial(3)
= 5 * 4 * 3 * factorial(2)
= 5 * 4 * 3 * 2 *factorial(1)
= 5 * 4 * 3 * 2 * 1
= 120

Related

Explain the Step by step execution of the recursion code to convert Decimal to Binary in Java

So, this is the code to convert a Decimal number to Binary number using recursion in Java, the code works without any error. But I am confused how does the compiler execute this code, like I was solving it using paper, but I am not able to understand how the compiler takes it and generates the output.
When I was solving it on paper the solution did not make any sense to me. If anybody can tell me how it works, please. Have been sitting on the problem for more than 1 hour now.
I would be happy if somebody describes me the step by step execution of the code and arriving at the same output as the code.
Have used recursion like shown below.
public class RecursionPractice {
public static void main(String[] args) {
System.out.println("The converted number is " + dectoBin(7));
}
private static int dectoBin(int n){
if(n == 0 )
return 0;
else
return n % 2 + 10 * dectoBin(n/2);
}
}
The output is as expected
The converted number is 111
Process finished with exit code 0
Step By Step Execution as follows. Hopefully you'll understand now .
1st call: dectoBin(7) => return 7 % 2 + 10 * dectoBin(7/2); => 1 + 10 * dectoBin(3);
2nd call: dectoBin(3) => return 3 % 2 + 10 * dectoBin(3/2); => 1 + 10 * dectoBin(1);
3rd call: dectoBin(1) => return 1 % 2 + 10 * dectoBin(1/2); => 1 + 10 * dectoBin(0);
4th call: dectoBin(0) => return 0; // base case
Evaluate all of these
dectoBin(7);
7 % 2 + 10 * dectoBin(3);
7 % 2 + 10 * ( 3 % 2 + 10 * dectoBin(1) );
7 % 2 + 10 * ( 3 % 2 + 10 * ( 1 % 2 + 10 * dectoBin(0) ) );
dectoBin(0) returns 0 So,
7 % 2 + 10 * ( 3 % 2 + 10 * ( 1 % 2 + 10 * 0 ) );
7 % 2 + 10 * ( 3 % 2 + 10 * ( 1 ) );
7 % 2 + 10 * ( 11 );
7 % 2 + 110;
1 + 110;
111;
1st Iteration:
7 % 2 + 10 * __
2nd Iteration
3 % 2 + 10 * __
3rd Iteration
1 % 2 + 10 * __
4th Iteration
return 0
3rd Iteration
1 % 2 + 10 * 0 = 1
2nd Iteration
3 % 2 + 10 * 1 = 1 + 10 = 11
1st Iteration:
7 % 2 + 10 * 11 = 1 + 110 = 111
Recursion is a type of loop, if you have a problem to solve in your code (maybe converting a list to string in a special formatting) but that that problem has more instances of the same problem within it (That list has more lists inside of it that needed to be formatted in the same way).
In your example the loop will stop when the decToBin() method is given 0 as an argument. The loop basically goes on and keeps dividing the number by 2 until it gets to 0 or less and then it stops.
Pass 7 to the method:
7%2 + 10 * dectoBin(7/2)= 1 + 10* dectoBin(3). Now n is 3.
(dectoBin(3)): 3%2 + 10* dectoBin(3/2) = 1 + 10 * dectoBin(1). Now n is 1
(dectoBin(1)): 1%2 + 10* dectoBin(1/2) = 1+ 10 * dectoBin(0). Now n is 0
(dectoBin(0)): return 0;
Going backwards: 1 + 10* (1 +10 *(1+10*0))=1+ 10*(1 + 10)= 1 +110 =111

Precedence in expression including parentheses and int cast in java [duplicate]

This question already has answers here:
Int division: Why is the result of 1/3 == 0?
(19 answers)
Closed 3 years ago.
I have the following expression in my code
int n = ((int) Math.sqrt(4 * 4 + 5) - 1) / 2;
Can someone tell me the precedence in which the expression is evaluated?
Logically I would evaluate the expression in the following way:
4 * 4 + 5 = 16 + 5 = 21
Math.sqrt(21) ~ 4.58
4.58 - 1 = 3.58
(int) 3.58 = 3
3 / 2 = 1.5
However the code evaluates to 1.
You almost got it. The only difference (which doesn't matter for the result) is that the cast is evaluated
before the subtraction, and you're using integer division:
4 * 4 + 5 = 16 + 5 = 21
Math.sqrt(21) ~ 4.58
(int) 4.58 = 4 (cast first)
4 - 1 = 3
3 / 2 = 1 (integer division)
The order you suggest is correct.
The keypoint is the last operation: the result of an int divided by an int is an int as well.
To fix this, one of the two number should be a float (or a double):
float n = ((float)(int) (Math.sqrt(4 * 4 + 5) - 1)) / 2;
In this way you divide a float by an int, and the result will be a float.
Or better:
double n = (Math.sqrt(4 * 4 + 5) - 1) / 2;
Because the cast to int of Math.sqrt() isn't useful.
Please note that the first operation does exactly what you ask with the round of the Math.sqrt(), while the second one doesn't.

Calculating Manhattan Distance within a 2d array

I am writing a program to solve an nxn 8 puzzle problem. I'm having difficulty with my Manhattan calculation function being off by two from the puzzle I'm testing my program with. This will eventually be expanded to use the A* pathfinding algorithm, but I'm not there yet.
Here is my function(which is based on the initial state of the board and not taking into account the amount of moves taken so far):
// sum of Manhattan distances between blocks and goal
public int Manhattan() // i don't think this is right yet - check with vince/thomas
{
int distance = 0;
// generate goal board
int[][] goal = GoalBoard(N);
// iterate through the blocks and check to see how far they are from where they should be in the goal array
for(int row=0; row<N; row++){
for(int column=0; column<N; column++){
if(blocks[row][column] == 0)
continue;
else
distance += Math.abs(blocks[row][column]) + Math.abs(goal[row][column]);
}
}
distance = (int) Math.sqrt(distance);
return distance; // temp
}
This is the example I'm working off of:
8 1 3 1 2 3 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
4 2 4 5 6 ---------------------- ----------------------
7 6 5 7 8 1 1 0 0 1 1 0 1 1 2 0 0 2 2 0 3
initial goal Hamming = 5 + 0 Manhattan = 10 + 0
My Hamming calculation is correct and returns 5, but my Manhattan returns 8 instead of 10. What am I doing wrong?
This is the output of my program:
Size: 3
Initial Puzzle:
8 1 3
4 0 2
7 6 5
Is goal board: false
Goal Array:
1 2 3
4 5 6
7 8 0
Hamming: 5
Manhatten distance: 8
Inversions: 12
Solvable: true
The error lies in the update of the distance.
In writing distance += Math.abs(blocks[row][column]) + Math.abs(goal[row][column]); you add all contents of the cells of initial and goal. Only one excluded in initial and goal is the cell with same coordinates as 0 in initial.
In your example this gives 2 times sum from 0 to 8 minus 5. 2 * 36 -8 = 64. Then you take the square which is 8.
Manhattan - as described by Wiktionary is calculated by distance in rows plus distance in columns.
Your algorithm must lock like (beware, pseudocode ahead!)
for (cell : cells) {
goalCell = findGoalcell(cell.row, cell.col);
distance += abs(cell.row - goalCell.row);
distance += abs(cell.col - goalCell.col);
}
And don't take the square root.

Iterative Maximization Algorithm

Here is the problem I am currently trying to solve.
There is a maximum value called T. There are then two subvalues, A and B, that are 1 <= A,B <= T. In each round, you can pick either A or B to add to your sum. You can also choose to half that sum entirely in only one of the rounds. You can never exceed T in any round. Given an infinite number of rounds, what is the maximum sum you can get.
Here's an example:
T = 8
A = 5, B = 6
Solution: We first take B, then half the sum getting 3. Then we add A and get 8. So the maximum possible is 8.
The iterative idea I have come up with is: it is basically a tree structure where you keep branching of and trying to build of older sums. I am having trouble trying to figure out a maximization formula.
Is there a brute force solution that will run fast or is there some elegant formula?
Limits: 1 <= A, B <= T. T <= 5,000,000.
EDIT: When you divide, you round down the sum (i.e. 5/2 becomes 2).
The problem can be viewed as a directed graph with T + 1 nodes. Imagine we have T + 1 nodes from 0 to T, and we have an edge from node x to node y if:
x + A = y
x + B = y
x/2 = y
So, in order to answer the question, we need to do a search in the graph, with stating point is node 0.
We can do either a breath first search or depth first search to solve the problem.
Update: as we can only do divided once, so we have to add another state to the graph, which is isDivided. However, the way to solve this problem is not changed.
I will demonstrate the solution with a BFS implementation, DFS is very similar.
class State{
int node, isDivided;
}
boolean[][]visited = new boolean[2][T + 1];
Queue<State> q = new LinkedList();
q.add(new State(0, 0));//Start at node 0, and haven't use division
visited[0][0] = true;
int result = 0;
while(!q.isEmpty()){
State state = q.deque();
result = max(state.node, result);
if(state.node + A <= T && !visited[state.isDivided][state.node + A]){
q.add(new State(node + A , state.isDivided));
visited[state.isDivided][node + A] = true;
}
if(node + B <= T && !visited[state.isDivided][node + B]){
q.add(new State(node + B, state.isDivided));
visited[state.isDivided][node + B] = true;
}
if(state.isDivided == 0 && !visited[state.isDivided][node/2]){
q.add(new State(node/2, 1));
visited[state.isDivided][node/2] = true;
}
}
return result;
Time complexity is O(n)
To summarize your problem setting as I understand it (under the constraint that you can divide by two no more than once):
Add A and B as many times as you want (including 0 each)
Divide by 2, rounding down
Add A and B as many times as you want
The goal is to obtain the largest possible sum, subject to the constraint that the sum is no more than T after any step of the algorithm.
This can be captured neatly in a 5-variable integer program. The five variables are:
a1: The number of times we add A before dividing by 2
b1: The number of times we add B before dividing by 2
s1: floor((A*a1+B*b1)/2), the total sum after the second step
a2: The number of times we add A after dividing by 2
b2: The number of times we add B after dividing by 2
The final sum is s1+A*a2+B*b2, which is constrained not to exceed T; this is what we seek to maximize. All five decision variables must be non-negative integers.
This integer program can be easily solved to optimality by an integer programming solver. For instance, here is how you would solve it with the lpSolve package in R:
library(lpSolve)
get.vals <- function(A, B, T) {
sol <- lp(direction = "max",
objective.in = c(0, 0, 1, A, B),
const.mat = rbind(c(A, B, 0, 0, 0), c(0, 0, 1, A, B), c(-A, -B, 2, 0, 0), c(-A, -B, 2, 0, 0)),
const.dir = c("<=", "<=", "<=", ">="),
const.rhs = c(T, T, 0, -1),
all.int = TRUE)$solution
print(paste("Add", A, "a total of", sol[1], "times and add", B, "a total of", sol[2], "times for sum", A*sol[1]+B*sol[2]))
print(paste("Divide by 2, yielding value", sol[3]))
print(paste("Add", A, "a total of", sol[4], "times and add", B, "a total of", sol[5], "times for sum", sol[3]+A*sol[4]+B*sol[5]))
}
Now we can compute how to get as high of a total sum as possible without exceeding T:
get.vals(5, 6, 8)
# [1] "Add 5 a total of 1 times and add 6 a total of 0 times for sum 5"
# [1] "Divide by 2, yielding value 2"
# [1] "Add 5 a total of 0 times and add 6 a total of 1 times for sum 8"
get.vals(17, 46, 5000000)
# [1] "Add 17 a total of 93 times and add 46 a total of 0 times for sum 1581"
# [1] "Divide by 2, yielding value 790"
# [1] "Add 17 a total of 294063 times and add 46 a total of 3 times for sum 4999999"
I'll use some mathematical approach.
Resume:
You should be able to calculate the max with A,B, T, without iterations (only to get A/B HCD), for T, not to small.
If A or B is an odd number, max = T (with a reserve, I'm not sure you never go over T: see below).
If A and B is even numbers, get C as highest common factor. Then max = round (T/C*2) *C/2 = highest multiple of C/2 below or equal to T
Some explanations:
With the rule: Ap+Bq (without dividing by 2)
1 suppose A and B are primes together, then you can get every integer you want, after the little ones. Then max=T
example: A=11, B=17
2 if A=Cx, and B=Cy, x,y primes together (like 10 and 21), you can get every C multiples, then max= biggest multiple of C below T: round(T/C)*C
example: A=33, B=51 (C=3)
With the rule : you can divide by 2
3 - If C is even number (that is A and B can be divided by 2): max= multiple of C/2 below T: round(T/C*2)*C/2
example: A=22, B=34 (C=2)
4 - Otherwise, you have to find the biggest dividor (highest common factor) of A, B, round(A/2), round (B/2), call it D, max= biggest multiple of D below T: round(T/D)*D
As A and round (A/2) are primes together (idem for B and round (B/2)), then you can get max = T as in case 1 - warning: I'm not sure if you never go past T. To check
We can describe the problem in this way aswell:
f(A , B) = (A * n + B * m) / 2 + (A * x + B * y)
= A * (n * 0.5 + x) + B * (m * 0.5 + y) =
= A * p + B * q
find N: N = f(A , B) and N <= T such that no M: M > N satisfying
the condition exists.
The case without any division by two can easily be represented by n = m = 0 and is thus aswell covered by f.
n and y can be any arbitrary values matching p = n * 0.5 + y (same for q and related values). Note that there are multiple valid solutions as shown in f.
T >= A * p + B * q
r = p * 2, s = q * 2
find integral numbers r, s satisfying the condition
T >= A * r / 2 + B * s / 2
simplify:
T * 2 / B >= A / B * r + s
Thus we know:
(T / B * 2) mod 1 - (A / B * r) mod 1 is minimal and >= 0 for the optimal solution
T * 2 / A >= r >= 0 are the upper and lower bounds for r
(A / B * r) mod 1 = 0, if r = B / gcd(A , B) * n, where n is an integral number
Finding r using these constraints now becomes a trivial task, using binary search. There might be more efficient approach to this, but O(log B) should do for this purpose:
Apply a simple binary-search to find the matching value
in the range [0 , min(T * 2 / A , B / gcd(A , B))
Finding s can easily be done for any corresponding r:
s = roundDown(T * 2 / B - A * r / B)
E.g.:
A = 5
B = 6
T = 8
gcd(A , B) = 1
search-range = [0 , 6)
(T / B * 2) mod 1 = 4 / 6
(A / B * r) mod 1 =
r = 3: 3 / 6 => too small --> decrease r
r = 1: 5 / 6 => too great --> increase r
r = 2: 4 / 6 => optimal solution, r is found
r = 2
s = roundDown(T * 2 / B - A * r / B) = roundDown(3.2 - 1.66) = 1
p = r / 2 = 1 = 1 + 0 = 2 * 0.5 --> n = 1 y = 0 or n = 2 y = 0
q = s / 2 = 0.5 --> n = 0.5 y = 0
8 >= 5 * 1 + 5 * 0.5 * 0 + 0 * 6 + 1 * 0.5 * 6 = 5 + 3
= 5 * 0 + 5 * 0.5 * 2 + 0 * 6 + 1 * 0.5 * 6 = 5 + 3
Advantage of this approach: We can find all solutions in O(log B):
If a value for r is found, all other values r' matching the constraints are as follows: r' = r + B / gcd(A , B) * n. A and B are exchangeable in this approach allowing to optimize even further by using the smaller input value as B.
The rounding of values when the variable is divided by two in your algorithm should only cause minor problems, which can easily be fixed.

Combinations function in Java

In one of the examples in my book it creates two methods. One called combinations and one called factorial. The body on the combinations method contains the following code
private int combinations(int n, int k){
return factorial(n) / (factorial (k) * factorial (n-k));
}
In an example of actually seeing how the math works out for this formula the textbook gives the following example. With n = 5 and k = 2. It gives the following steps and says you should get 10. I'm having difficulty understating the logic.
Does ! have a special meaning in this case? How does 5! = 120 and how does !2 x !3 = 2 x 6?
C (n,k) = n!
_________
k! x (n - k)!
C (5,2) = 5!
___________
2! x !3
= 120
_________
2 x 6
= 10
n! means factorial(n). It is equal to: -
n! = n * (n - 1) * (n - 2) * .... * 1
So,
5! = 5 * 4 * 3 * 2 * 1 = 120
And !3 is rather a typo in your book. It doesn't represent a factorial
! denotes a factorial.
5! = 120
because
5! = 5 * 4 * 3 * 2 * 1
and
2! x 3! = 2 * 6
because
2! x 3! = (2 * 1) * (3 * 2 * 1)
Factorial
The ! (factorial) symbol means the product of all integers up to and including the number. So, for example:
5! = 5 * 4 * 3 * 2 * 1 = 120
This should help clarify what the factorial(int) method is doing.
By the way, if your book actually printed "!3" instead of "3!", it's a typo.

Categories