I am trying to understand this particular solution of Towers of Hanoi problem. It is a recursive solution.
A = [5, 4, 3, 2, 1]
B = []
C = []
def move(n, source, target, auxiliary, frm):
print('n here : ', n)
if n > 0:
print('frm : ', frm, n)
# move n - 1 disks from source to auxiliary, so they are out of the way
move(n - 1, source, auxiliary, target, '1')
# move the nth disk from source to target
target.append(source.pop())
print('n:', n)
# Display our progress
print(source, target, auxiliary, '##############', sep = '\n')
# move the n - 1 disks that we left on auxiliary onto target
move(n - 1, auxiliary, target, source, '2')
# initiate call from source A to target C with auxiliary B
move(5, A, C, B, '0')
You can see it live here
https://repl.it/JUzY/0
After the first line of ######### gets printed, the value of n = 0, becomes 2. How does this happen? Am I missing out some concept of recursion ? Help me in understanding this.
You need to understand scope. You say "the value of n = 0, but suddenly it becomes 2". But there is more than one "n", because the scope of n is the method. Each time move gets called, that method call has its own instance of n with its own value.
At the bottom of the script, you call move(5, A, C, B, '0'). Inside that call, n == 5. The first thing that does is call move(n - 1, source, auxiliary, target, '1'). Inside that call, n == 4. But when it eventually returns, n in the original function call is still 5.
A good way to understand how recursion works, is to work through the program execution by hand, using sheets of paper. I'm going to use a Post-It note for function calls, and a notebook for output. You also have your "model", in the form of the lists A,B,C. Since elements move around, you could represent those elements with scraps of paper or scrabble tiles.
Start with the intial move(4, A, C, B, '0'). (I'm starting at 4 because the number of steps grows rapidly). Since we are calling a function, take a new post-it to represent the function call, and write on it:
n = 4
source = A
target = C
auxiliary = B
frm = '0'
Now work through the code of move doing what it says. Write any print output on this one.
When you reach the call to move(n - 1, source, auxiliary, target, '1'), make a note on the post-it of the line number you're at, then get a new post-it, and write the values that are going into it:
n = 4 (because 4 - 1)
source = A
target = B (caller's auxiliary)
auxiliary = C (caller's target)
frm = '1'
Place this on top of the previous post-it. You are not allowed to look at the covered up post-it until it's revealed again. Keep doing this, and you'll end up with a stack of five post-its.
The fifth post-it has n = 0. Now when you step through its code, because it starts with if n > 0:, the call returns immediately. This function call is over, so tear up that one post-it and throw it away. The values of n etc. in that post-it have no effect on the other post-its.
You made a note of the line-number you were at, so carry on executing the code by hand from that line. You will produce some output, then call move again -- use post-its for this move too, again covering up the current post-it and growing your stack until you make a call with n == 0 and can remove an item from the stack.
If you keep doing this, you'll see the stack grow and shrink several times, you'll reach the original post-it once, do its print, then grow the stack again, then reach the original post-it again, and finally finish.
The stack of post-it notes is an exact model of the execution stack of a program's runtime. When you see stack traces (even of non-recursive programs), this is what they represent. Each post-it is a stack frame, and local variables have a scope that is restricted to that stack frame.
The recursive solution to Hanoi can be expressed in English as:
To move a stack of size zero, do nothing
To move a bigger stack from src to destination via auxiliary:
First move n-1 discs from src to auxiliary (to get them out of the way)
do that the same way we are doing this.
Then move the revealed disc to destination
Then move the n-1 discs from auxiliary to destination, using src as a spare peg
do that the same way we are doing this
Related
total number of ways to reach the nth floor with following types of moves:
Type 1 in a single move you can move from i to i+1 floor – you can use the this move any number of times
Type 2 in a single move you can move from i to i+2 floor – you can use this move any number of times
Type 3 in a single move you can move from i to i+3 floor – but you can use this move at most k times
i know how to reach nth floor by following step 1 ,step 2, step 3 any number of times using dp like dp[i]=dp[i-1]+dp[i-2]+dp[i-3].i am stucking in the condition of Type 3 movement with atmost k times.
someone tell me the approach here.
While modeling any recursion or dynamic programming problem, it is important to identify the goal, constraints, states, state function, state transitions, possible state variables and initial condition aka base state. Using this information we should try to come up with a recurrence relation.
In our current problem:
Goal: Our goal here is to somehow calculate number of ways to reach floor n while beginning from floor 0.
Constraints: We can move from floor i to i+3 at most K times. We name it as a special move. So, one can perform this special move at most K times.
State: In this problem, our situation of being at a floor could be one way to model a state. The exact situation can be defined by the state variables.
State variables: State variables are properties of the state and are important to identify a state uniquely. Being at a floor i alone is not enough in itself as we also have a constraint K. So to identify a state uniquely we want to have 2 state variables: i indicating floor ranging between 0..n and k indicating number of special move used out of K (capital K).
State functions: In our current problem, we are concerned with finding number of ways to reach a floor i from floor 0. We only need to define one function number_of_ways associated with corresponding state to describe the problem. Depending on problem, we may need to define more state functions.
State Transitions: Here we identify how can we transition between states. We can come freely to floor i from floor i-1 and floor i-2 without consuming our special move. We can only come to floor i from floor i-3 while consuming a special move, if i >=3 and special moves used so far k < K.
In other words, possible state transitions are:
state[i,k] <== state[i-1,k] // doesn't consume special move k
state[i,k] <== state[i-2,k] // doesn't consume special move k
state[i,k+1] <== state[i-3, k] if only k < K and i >= 3
We should now be able to form following recurrence relation using above information. While coming up with a recurrence relation, we must ensure that all the previous states needed for computation of current state are computed first. We can ensure the order by computing our states in the topological order of directed acyclic graph (DAG) formed by defined states as its vertices and possible transitions as directed edges. It is important to note that it is only possible to have such ordering if the directed graph formed by defined states is acyclic, otherwise we need to rethink if the states are correctly defined uniquely by its state variables.
Recurrence Relation:
number_of_ways[i,k] = ((number_of_ways[i-1,k] if i >= 1 else 0)+
(number_of_ways[i-2,k] if i >= 2 else 0) +
(number_of_ways[i-3,k-1] if i >= 3 and k < K else 0)
)
Base cases:
Base cases or solutions to initial states kickstart our recurrence relation and are sufficient to compute solutions of remaining states. These are usually trivial cases or smallest subproblems that can be solved without recurrence relation.
We can have as many base conditions as we require and there is no specific limit. Ideally we would want to have a minimal set of base conditions, enough to compute solutions of all remaining states. For the current problem, after initializing all not computed solutions so far as 0,
number_of_ways[0, 0] = 1
number_of_ways[0,k] = 0 where 0 < k <= K
Our required final answer will be sum(number_of_ways[n,k], for all 0<=k<=K).
You can use two-dimensional dynamic programming:
dp[i,j] is the solution value when exactly j Type-3 steps are used. Then
dp[i,j]=dp[i-1,j]+dp[i-2,j]+dp[i-3,j-1], and the initial values are dp[0,0]=0, dp[1,0]=1, and dp[3*m,m]=m for m<=k. You can build up first the d[i,0] values, then the d[i,1] values, etc. Or you can do a different order, as long as all necessary values are already computed.
Following #LaszloLadanyi approach ,below is the code snippet in python
def solve(self, n, k):
dp=[[0 for i in range(k+1)]for _ in range(n+1)]
dp[0][0]=1
for j in range(k+1):
for i in range(1,n+1):
dp[i][j]+=dp[i-1][j]
if i>1:
dp[i][j]+=dp[i-2][j]
if i>2 and j>0:
dp[i][j]+=dp[i-3][j-1]
return sum(dp[n])
In my situation I have territory objects. Each territory knows what other territories they are connected to through an array. Here is an visualization of said territories as they would appear on a map:
If you were to map out the connections on a graph, they would look like this:
So say I have a unit stationed in territory [b] and I want to move it to territory [e], I'm looking for a method of searching through this graph and returning a final array that represents the path my unit in territory [b] must take. In this scenario, I would be looking for it to return
[b, e].
If I wanted to go from territory [a] to territory [f] then it would return:
[a, b, e, f].
I would love examples, but even just posts pointing me in the right direction are appreciated. Thanks in advance! :)
Have you heard of Breadth-First Search (BFS) before?
Basically, you simply put your initial territory, "a" in your example, into an otherwise empty queue Q
The second data structure you need is an array of booleans with as many elements as you have territories, in this case 9. It helps with remembering which territories we have already checked. We call it V (for "visited"). It needs to be initialized as follows: All elements equal false except the one corresponding to the initial square. That is for all territories t, we have V[t] = false, but V[a] = true because "a" is already in the queue.
The third and final data structure you need is an array to store the parent nodes (i.e. which node we are coming from). It also has as many elements as you have territories. We call it P (for "parent") and every element points to itself initially, that is for all t in P, set P[t] = t.
Then, it is quite simple:
while Q is not empty:
t = front element in the queue (remove it also from Q)
if t = f we can break from while loop //because we have found the goal
for all neighbors s of t for which V[s] = false:
add s into the back of Q //we have never explored the territory s yet as V[s] = false
set V[s] = true //we do not have to visit s again in the future
//we found s because there is a connection from t to s
//therefore, we need to remember that in s we are coming from the node t
//to do this we simply set the parent of s to t:
P[s] = t
How do you read the solution now?
Simply check the parent of f, then the parent of that and then the parent of that and so on until you find the beginning. You will know what the beginning is once you have found an element which has itself as the parent (remember that we let them point to itself initially) or you can also just compare it to a.
Basically, you just need a empty list L, add f into it and then
while f != a:
f = P[f]
add f into L
Note that this obviously fails if there exists no path because f will never equal a.
Therefore, this:
while f != P[f]:
f = P[f]
add f into L
is a bit nicer. It exploits the fact that initially all territories point to themselves in P.
If you try this on paper with you example above, then you will end up with
L = [f, e, b, a]
If you simply reverse this list, then you have what you wanted.
I don't know C#, so I didn't bother to use C# syntax. I assume that you know it is easiest to index your territories with integers and then use an array to access them.
You will realize quite quickly why this works. It's called breadth-first search because you consider only neighbors of the territory "a" first, with trivially shortest path to them (only 1 edge) and only once you processed all these, then territories that are further away will appear in the queue (only 2 edges from the start now) and so on. This is why we use a queue for this task and not something like a stack.
Also, this is linear in the number of territories and edges because you only need to look at every territory and edge (at most) once (though edges from both directions).
The algorithm I have given to you is basically the same as https://en.wikipedia.org/wiki/Breadth-first_search with only the P data structure added to keep track where you are coming from to be able to figure out the path taken.
Write a function called connectTheDots that takes in a list of tuples as its input and an optional color input as well. The default color value should be black. Each tuple is a coordinate pair (x, y) for a turtle. The function will have the turtle trace out a picture by starting at the first coordinate and then moving to each coordinate in turn.
Your function should do the following:
a. Create a turtle, setting the turtle’s color and speed appropriately
b. Check if the input list is empty: if it is empty then nothing else should happen!
c. Without leaving a line behind, move the turtle to the first location given in the list. Then start leaving a line again. Note: recall how to pull values out of a list, and also know that the goto method can take a single (x, y) tuple as its input: myTurtle.goto( (25, 25) ) will move myTurtle to x = 25 and y = 25.
d. After the turtle is at the starting coordinate, move it to each coordinate in the list in turn.
This is what I have been able to do so far:
def connectTheDots(list1, color ="black"):
myTurtle = turtle.Turtle()
myTurtle.speed(1)
myTurtle.goto(list1[0])
for x,y in list1[1:]: #I'm unsure if this is correct
myTurtle.goto(x,y)
You have most of what you need but are probably making it more complicated than needed and are missing some small details.
For step "a" you need to explicitly set the color (you passed it in just fine). You are probably better off using a symbolic speed instead of a numeric one.
For step "b", if you have a proper for ... in loop, you don't need to explicitly check if the list is empty as the loop won't run if it is. Your splitting off the first item myTurtle.goto(list1[0]) works against you here as there may not be one, causing an IndexError.
For step "c" you need to add another command. Turtles start life in the center of the screen with their pens down. You need to raise the pen up after creating your turtle. But you don't need to explicitly move to the starting position, let your loop handle that.
The trick we'll use for step "c" and step "d" is to put the pen down after the goto() in the loop. The first time, this actually puts the pen down, after that, it's a harmless no-op:
import turtle
def connectTheDots(coordinates, color="black"):
myTurtle = turtle.Turtle()
myTurtle.speed("slowest")
myTurtle.color(color)
myTurtle.penup()
for coordinate in coordinates:
myTurtle.goto(coordinate)
myTurtle.pendown() # redundant after first iteration
dots = ((34, 56), (100, 240), (230, 105), (34, 56))
connectTheDots(dots, "green")
turtle.done()
If it bothers you that we're putting the pen down unnecessarily in the loop, then we can replace myTurtle.pendown() with:
if not myTurtle.isdown():
myTurtle.pendown()
I guess only 1 stack wouldn't be enough, because the following logic doesn't look very viable to me:
De-Casteljau's-algorithm
Everything can be done with a stack.
De Casteljau's algorithm is an iterative algorithm that replaces:
{a,b,c,d,...,z}
with:
{a'=lerp(a,b), b'=lerp(b,c), c'=lerp(c,d), ..., y'=lerp(y,z)}
and runs that reduction until there is only one value left.
Using a stack, we take the two bottom stack elements, lerp them (based on some ratio value), and then overwrite the bottom element with the resulting value. We move up one spot, and repeat, move and repeat, move and repeat, until we reach the top of the stack. Then we discard the topmost element. To find the final point, we run that algorithm until the stack is size 1.
So, in pseudo-code:
reduceOnce(stack, ratio):
n = stack.length
for(i = 0 to n-1):
stack[i] = (1-ratio) * stack[i] + ratio * stack[i+1]
stack.pop()
stackReduce(stack, ratio):
while(stack size > 1):
reduceOnce(stack, ratio)
And done: one stack needed.
I don't know how to start on it.
Let's image a 5x5 square.
The robot starts on the upper left-hand corner and ens on the bottom right-hand corner.
We would like to have a robot travel from the start square at the upper left to the end square at the lower right.
At each square, the robot has only one of two moves:
It may go one square to the right or
It may go one square down.
Write a program to determine how many ways may this be done? In other words, how many paths are there from “start” to “end” with the moves at each step restricted as above?
This is represented by a recursive tree traversal. You can write a single recursive method to do this, something like:
traverse_moves, taking a board state (where the robot is, in this case) and returning an integer
Compute the next moves you can make - from 0 to 2 total. If 0, return the integer 1. If 1 or 2, create the board state for each valid move and call this method with the state you created, summing the return values of all of your calls and returning the sum you got.
e.g. for a 2x2 board, create the state where the robot is in the top left. This state has two possible moves, so it will call itself with robot bottom left and robot top right. Each of those states has one possible move and will call themself with robot bottom right. Both of these 'leaves' of the traversal tree will return 1, and these 1s will be returned and propagated and summed up the recursive to give you 2 as the correct answer.
Caller
| 2
TL calls itself with BL and TR
/ 1 \ 1
BL TR call themselves with BR, their only valid move
| 1 | 1
BR BR return 1s each for being leaf nodes, the 1s are returned and summed
EDIT: pseudocode
int traverseMoves(BoardState state)
{
List<BoardState> nextMoves = possibleMovesFrom(state);
if (nextMoves.Length == 0)
{
return 1;
}
int returnValue = 0;
foreach (BoardState move in nextMoves)
{
returnValue += traverseMoves(move);
}
return returnValue;
}