Understanding this recursive function - java

Hello fellow programmers.
For some time now, recursive programming have been one of the things i understand the least. Because of that i decided, that i needed to use some time, understanding and programming a few basic examples. The problem is that i have this assignment i solved, but dont quite understand how it works -.-
If someone could help me understand it, i would appreciate it.
Thanks, in advance.
Teilmann
Assignment:
A dominopiece has the size 2*1. A board has the length n and width 2. Create a recursive method that returns the number of ways, whereas a board can be covered by dominopieces.
My method:
public static int dominobrik(int n){
int sum;
if(n >= 0 && n <= 2){
sum = n;
} else {
sum = dominobrik(n-1) + dominobrik(n-2);
}
return sum;
}

To help people understand this kind of recursive calls I really think that nicely printing things out really helps.
The output of the program has been indented according to the recursion depth.
Here are the 8 paths taken to reach all the solution for a width of 5, when doing:
dominobrik(n-2) + dominobrik(n-1)
(notice that for each new path, the recursive calls first adds the two horizontal pieces if possible)
(also note that this is different than the code you posted, where you wrote (n-1) first and then (n-2), but it really doesn't change much)
So far the board is:
.....
.....
So far the board is:
--...
--...
So far the board is:
----.
----.
Finished board:
----|
----|
So far the board is:
--|..
--|..
Finished board:
--|--
--|--
So far the board is:
--||.
--||.
Finished board:
--|||
--|||
So far the board is:
|....
|....
So far the board is:
|--..
|--..
Finished board:
|----
|----
So far the board is:
|--|.
|--|.
Finished board:
|--||
|--||
So far the board is:
||...
||...
So far the board is:
||--.
||--.
Finished board:
||--|
||--|
So far the board is:
|||..
|||..
Finished board:
|||--
|||--
So far the board is:
||||.
||||.
Finished board:
|||||
|||||

In the base case, where n = 1, there is only 1 way to arrange the domino on the board, and that's horizontally. Where n = 2, there are 2 ways to arrange the dominoes. Either you can arrange both vertically, or both horizontally.
For the case where n = 3, the 3 ways are:
1 horizontally across the top, and two vertically beneath;
1 horizontally across the bottom, and 2 vertically above;
or all 3 horizontally, stacked.
Note that in the n = 3 case, you have repeated both of the arrangements of the n = 2 case, but to these, you have added the arrangement from the n = 1 case. Recall that the only valid arrangement for n = 1 is a single horizontal domino. Each of the cases in n = 3 has at least 1 horizontal domino.
You can extend this to the n = 4 case. Take all of the possible combinations above for n = 3, then add all of the combinations for n = 2, stacking them appropriately given the problem's constraints.
I wish I could illustrate this, but it may help to draw them out on some squared paper.

Le't say you know the answer for n and you want the answer for n + 1.
For some of the solutions for n, you have the last domino standing vertically and for the others, the last two dominos are stacked horizontally one over the other.
If the last two dominos are horizontal, all you can do is add your n + 1 domino vertically. However if the last domino is vertical, then you can add it vertically too, or you can flip it horizontally with the previous domino.
I would keep track not only of how many solutions there are for a given n, but also of how many of those are terminating with the last domino horizontal/vertical.
I'll let you figure out the rest since this is homework. Also I haven't really figured out the complete solution. It's possible it will turn out to be equivalent to the solution you posted.

Related

All combinations of 2d array chess game

I am making a program that is calculating the number of possible solutions of a chess game with only bishops and queens. The user can put in the number of queens and bishops, as well as the size of the chess board (rows & columns).
I will call any set of positions for the bishops and the queens on the board a combination. A combination counts as a solution if all squares are attacked (Chess domination problem).
So for example, if the user gives 1 Queen and 3 Bishops, on a 5x5 chess board, a possible solution can be:
- - B - -
- - - - -
- B Q B -
- - - - -
- - - - -
Now i have trouble making a program that finds all the possible positions of a given set of pieces, without duplicates. Duplicates can occur because the user can give a multiple number of bishops for example. The solution needs to be recursive.
You don't show your current solution, but I /assume/ you pick each square for the first piece, then pick each square for the second piece , and continue if the square is still unoccupied. Then repeat for the third, etc.
If the first and second piece are the same type, then this will cause a duplication. First piece in first position, second in second vs first in second position, second in first.
If you have two pieces of the same type, you can just impose an ordering on your positioning the second piece: Do not place the second identical piece at a lower index than the first. This avoids the duplication, but still visits every permutation of positions. You can impose this ordering on more of the same types of piece.
When you have a different type of piece, the two orderings become distinct. If the first and second are different piece types, then First piece in first position, second in second vs first in second position, second in first are distinct cases. However, when you put down the second instance of the new type, you can apply the ordering rule against the first one.
[Alternatively, you can insist that the second piece is placed before the first piece - the outcome is the same]
As a second optimisation, you can observe that if you have 3 bishops and the third must be placed after the other 2, then the first cannot be placed in the last or penultimate squares, so you can optimise your placement of the first one very slightly.
This becomes more complex when this is the second type of piece, and it is possibly not worth doing.
A third optimisation is to keep a list of the available squares. Once a piece is put down, its square is removed from the list, so the list is shorter for placing the next piece, and you don't have to "fail" when you try and put the queen on top of a bishop, as you won't try. You can use the length of this list to simplify the second optimisation.
You can do some clever tricks with std::list::splice to mean that you don't reallocate or duplicate this list as you recurse through the pieces and positions.

Stacking Tiles (Hard algorithm)

This is a question from a code competition, I am finding it unbelievably difficult to come up with any working algorithm to solve it. So I'm not really looking for the code but rather a step by step algorithm on how to solve it.
Stacking Tiles
Stacking tiles against the wall is one of Bongani's favourite pasttimes. His tiles all have the same thickness, but vary
in width and height. Bongani is given N tiles and has to use them in
the sequence given according to a set of rules. He can place a tile on
top of another only if it is narrower than the previously stacked
tile. Bongani is allowed to rotate the tiles by 90 degrees so that
width becomes height and height becomes width. He is also allowed to
discard a tile altogether. Given a list of tiles, help Bongani find
the highest stack he can build The example specifies tiles (3, 3),
(12, 5), (5, 8), (6, 10). To get the highest stack Bongani ignores the
first tile (3, 3) as it is smaller than the next tile. He uses the
next tile (12, 5) with 12 as the width and 5 as the height. He uses
the next two tiles with 8 as the width and 5 as the height followed by
6 as the width and 10 as the height.
The only thing I can possibly think of is getting every possible valid permutation of tiles and find the highest permutation.
The exact question can be found here http://www.olympiad.org.za/olympiad/wp-content/uploads/2013/01/2011PO-R2-Questions-0421.pdf (Question 5)
Here's an outline of dynamic programming solution:
You "move from left to right" and for each tile you figure out
how high tower can I build by using this tile unrotated
how high tower can I build by using this tile rotated
how high tower can I build by not using this tile
The first key observation is that each question can be answered recursively ("how high tower can I build for the remaining tiles if the current width is updated according to my current choice?"). Pseudo code:
maxHeight(tiles, currentWidth) {
// Base case
if (tiles.isEmpty())
return 0; // no tiles -> maxHeight == 0
int h = 0;
currentTile = tiles[0]
remainingTiles = tiles[1...]
// Compute maxHeight for the case when not using current tile
h = max(h, maxHeight(remainingTiles, currentWidth)
// Compute maxHeight when using current tile
if (currentWidth > currentTile.width)
subHeight = maxHeight(remainingTiles, currentTile.width)
h = max(h, subHeight + currentTile.height)
// Compute maxHeight when using current tile rotated
if (currentWidth > currentTile.height)
subHeight = maxHeight(remainingTiles, currentTile.height)
h = max(h, subHeight + currentTile.width)
return h
}
The second key observation is that many of the invocations of maxHeight have the same arguments, which means that previous computations can be reused. You can either use memoization or tabulation (both are variants of dynamic programming) If you choose to use a tabulation matrix, it would look like this:
M[tileN][width] = the height of the tower possible to build from
tileN onwards with width 'width'
(As you may note width does not have a clear upper bound. This can be solved by mapping all values to 1, 2, 3, ... before starting. Maximum width will then be 2N.)
Here is a quadratic time algorithm using dynamic programming. Let f(i) be the greatest height of a tower you can build using the ith block in the original orientation and no later blocks. Let g(i) be the greatest height of a tower you can build with the ith block rotated and no later blocks. Note that blocks can be omitted, so to compute f(i), you have to take 1 more than the maximum over all previous f and g values compatible with that orientation, and similarly for g(i). At the end, the answer is the maximum over all f(i) and g(i).
The following code shows code for f. Youc an write g similarly, or modify this to take another parameter for whether block i is in the original orientation.
public int f(int i)
{
if (i == 0)
return 1;
if (memoF[i] > 0)
return memoF[i];
int maxFound = 1; // using just this block is legal
for (int j = 0; j<i; j++){
if (widths[i] < widths[j])
maxFound = Math.max(f(j)+1,maxFound);
if (widths[i] < heights[j])
maxFound = Math.max(g(j)+1,maxFound);
}
memoF[i] = maxFound;
return memoF[i];
}
I think this is typical example for easy and effective solving using Backtracking.
You just go in sequence and try first things you can do, when you cant continue, you go back and try the one you did not try before. Just google "Sudoku Backtracking" there are a lot of pages explaing that.
The huge advantage of backtracking in this case is, it "cuts" off a lot scenariou which would make no sense, therefore it would be much more effective than trying to check every possible combination.
(like in sudoku, with backtracking, the most sudokus are solved in 1000-10000 steps, which is pretty good, given that the all possible combinations of numbers you can write are ~10^60)

Presidential Seating Backtracking

I have a problem in front of me that I can't grasp, even though I grasp the concept of backtracking well. I have been unable to find any information on this specific problem, and I am unaware if it goes by another name. The problem is to construct a backtracking algorithm that will print out the list of combinations of seating that N number of "presidents" can sit at a round table without sitting next to the same person twice. For example, you give it an input 8, it gives you the output,
1 2 3 4 5 6 7 8
1 3 5 2 6 8 4 7
1 4 2 7 5 8 3 6
Now I have constructed my own backtracking algorithms for simple games (checkers, n-queens, tic-tac-toe), however these that I have worked with have started with a blank canvas and didn't require this type of implementation. What I am asking for is a bit of guidance and insight, or links to more information to this problem as all that was given was about a page and a half, mostly talking about how the combination 1 2 3 4 is effectively the same as 1 4 3 2 in this particular problem. This needs to be done using a backtracking method and that's what is making me confused. If we were give free rein to find solutions I could easily do it. Any help is appreciated.
Thanks!
I'm thinking you'll have to add information about who sat next to who already to the backtracking algorithm state:
You start with, say 1. You seat 2 next to him, and record this "pairing" in the current partial solution. (Literally just an unordered pair of president IDs. An easy way of implementing an unordered pair of numbers is to have the constructor of that class store the smaller ID in the first element of the pair, and the greater ID in the second element.) So you have a partial solution 1 2 …, with the pairing 1-2.
When you reach to a complete solution, you add all its pairings to a "global" list of pairings. This will be used in future searches. I.e. if you get the solution 1 2 3 4 5 6 7 8, you save the pairings 1-2, 2-3, 3-4, 4-5, 5-6, 6-7, 7-8, 1-8.
Now, when doing a search, you have a partial solution x y z … – the last president seated so far is z, and the pairings in this partial solution are x-y and y-z. To seat the next president, you need to look at every president that's:
Not seated so far. (And thus not included in the partial solution's pairings.)
Not paired with z in the global pairings.
If no such president is available, you discard the partial solution and backtrack.
That said, I'm working off the top of my head here, so you'd be well advised to actually doublecheck if I missed any edge cases by using a straightforward brute force implementation and comparing the results.
A very rough pseudocode will look like this:
global flag // I know it is a bad practice but can't think of a better idea at this point
back (PresidentList, chairNumber, computedList)
if (PresidentList.size() == 0)
if (computedList doesn't violate any global distribution)
add computedList to globalList
add distirbution of computedList to global distirbution
set flag;
else return;
else if (flag is set and chairNumber > 2) return;
else if (flag is set and chairNumber = 2) un set flag; return;
else if (chairNumber == maxChairs-1)
// at this point there should be only one president in PresidentList
if (PresidentList.back() can sit with computedList.back() and computedList.front())
remove president from PreseidentList, add president to computedList
back(PresidenList, chairNumber+1,computedList)
else return;
else
for every president in PresidentList
if (president can sit with computedList.back())
remove president from PreseidentList, add president to computedList
back(PresidentList,chairNumber+1,computedList);
You always check if a president can sit near some other president only according to the global distribution variable.
In the main function just run a loop for PresidentList that will start back with that president being as the first one.
The idea of the flag is as follows: when you add a distribution and a list to the global list, back runs already a lot of branches which have the same prefix as the list you just added and hence are already bad. To close all those lists you force the back to stop branching and return to the point when it can set a new 2nd element in the list to compute i.e. get back to the loop if the last else branch of the function.

good way to seperate List<Integer> into 5 lists of chunks around the 5 minimums

Ok guys, time to get creative.
I have a list of integers, and want to preserve the integers in the 5 green boxes below.
I thought about finding the 5 minimums, and then going left and right from each one until the next integer is a certain distance too far. However this may be difficult to do as the last to boxes have some scattered values that I would like to maintain.
So cliff notes,
have list of integers that i want to make 5 lists of integers from, each one of the 5 lists holding the values of one of the green boxes.
I am sorry if this question seems dumb, I was just wanting to see if other people had better ways of going about this then the one I mentioned above.
Edit:
Perhaps a Levenberg-Marquardt algorithm would help? If only I could understand math books xD. I swear math explanations are never written in English, but if someone just shows me the use, and how to, I get it and understand it. Then I can go read it out of a book again and just be confused all over again!
That could be a possible solution:
Let call your list of integer P[n].
define a new list of point, we call it MAX[n], calculated this way:
if ((MAX[n] < P[n]) || (n == 0))
MAX[n] = P[n];
else
MAX[n] = MAX[n-1];
in this way, MAX[n] list will be the green line above your graph:
FIRST SOLUTION:
to identify the points inside the green boxes, you just have to calculate the incremental ratio of your P list, and check when its absolute value is smaller than a threshold:
I = [P[n+1] - P[n]] / [T[n+1] - T[n]]
so a point is into the green box if I is below a threshold and P is below MAX:
if ((P[n] < MAX[n]) && (ABS(I) < DER_THRESHOLD))
// your point is inside the green box
from your graph, roughtly, you could put DER_THRESHOLD = 5.
SECOND SOLUTION:
calculate a new list of integers, called this time AVG[n] like that:
AVG[n] = (MAX[n] + P[n]) / 2
this will end in the red line (sorry for the ugly graph, did it by hand):
and now you can identify green boxes just checking if your P[n] is below AVG[n].
This solution could be even better using some kind of low filtering in AVG calculation.
Try finding the least squares fit line through the points, and then look at whether the points are above or below the line. That will split your points into the five green boxes below the line, and the six infrared boxes above the line. It will also include the points inbetween the boxes, but those will be easy to exclude because of the big jump before or after the point that should be excluded. But it's also looking like you may have trouble at the top right of this data set.

Find available "number" in a 2d array

I have this problem that I need to solve in the most effecient way.
I have a 2d array that contains the following:
Everything that is a 1 is a "wall" which means you cannot go through it. 2 is the entrance where you "enter" the array or map if you like. 3 are the things we need to find. Here is an example of a map:
1111111
1 3131
2 11111
1 31
1111111
This could be an example of an array that i need to look in. As you can see there is a 3 that is "unreachable, since it's surrounded by a wall "1". Which means that there are two available numbers in this array.
First we need to find the entrance. Since the entrance can be anywhere I need to search the entire array. I have done the following:
int treasureAmount = 0;
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; i++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
This takes O(n^2) time, and i don't really see another way to do this, since the entrance can be anywhere.
However i'm not really sure how to find the available numbers effectivly and fast. I thought about while searching the arrays for the entrance i will at the same time find the all the number 3 in the array even though some might not be accessible, and after that i'm not really sure how to effectivly find which are accessible.
You cannot do it better that O(n^2). It will take that much time just to read the array. But then you could do a depth first search to find the reachable 3's in the array. Here is the pseudo code.
main()
{
read array and mark the entrance as ent.x and ent.y and also an array threex[] and threey[] that stores all the exit position.
boolean visited[][]; //stores whether array[i][j] is reachable or not.
dfs(ent.x,ent.y);
for each element in three arrays
{
if(visited[threex[i]][threey[i]]) print ("Reachable");
else print("not reachable", threex[i], threey[i]);
}
}
int dx[]={1,0,-1,0},dy[]={0,1,0,-1}; // dx[i], dy[i] tells whether to move in E,N,W,S respectively.
dfs(int x,int y)
{
visited[x][y]=true;
for(i=0;i<4;i++)//move in all directions
{
int newx=x+dx[i],newy=y+dy[i];
//check if this is within the array boundary
if(newx>=0&&newx<N && newy>=0&&newy<N)
if(!visited[newx][newy] && array[newx][newy]!=1) // check if the node is unvisited and that it is pemissible
dfs(newx,newy);
}
}
Since each array element is taken up not more than once in the dfs function the complexity of the code is O(n^2).
When creating the array, you can keep a list of coordinates of that have the value of 2. You can traverse that list in O(n).
Since both entrance and target items can be anywhere in the array you don't have much choice, but to search everything. So, your entrance search is as efficient as it can be, and regarding the target items I recommend the maze flood fill algorithm.
However, the linked version of the algorithm favorizes one direction (like it is filling it with water, it floods "down"). To be as efficient as it can, you should make it expand in all directions (like you're filling it with gas), e.g.:
2
1 212
0 101 21012
1 212
2
The numbers represent the iterations of expansion. The expansion is made in four directions: left, right, up and down. When you reach the target item, you can find the shortest route simply by backtracking to the adjacent cell neighbour whose iteration index is lesser by one, until you return to the 0 iteration index - the entrance.

Categories

Resources