简体   繁体   中英

to find the k-th move in an Hanoi Tower

def hanoi_move ( start , via , target ,n ,k ):
    """ finds the k-th move in an Hanoi Towers instance
    with n discs """
    if n <=0:
        return "zero or fewer disks"
    elif k <=0 or k >=2** n or type(k )!= int :
        return "number of moves is illegal"
    elif k ==2**( n -1):
        return str . format ("disk {} from {} to {}",n , start , target )
    elif k <2**( n -1):
         return hanoi_move ( start , target , via ,n -1 , k)
    else:
        return hanoi_move ( via , start , target ,n -1 ,k -2**( n -1))

why to look at the 2^(n-1) move? may you explain the code?

The TL;DR version - it takes 2^(n-1)-1 moves to move a stack of n-1 disks from one position to another, so this code is looking at if you are moving the n-th disk, or moving the stack of n-1 disks on or off of the n-th disk.

Full Answer:

Understanding why this code looks at the (n-1)th move in order to determine what the k-th move is requires understanding the basic idea behind moving the entire hanoi tower.

Let's look at an example. We have spots A, B, and C, and a tower of 10 disks starting at position A that we want to move to position C. We'll say disk 9 is the largest, next largest is 8, etc. To start off with, it looks like this:

A 9876543210
B
C

So how do we move everything to C? Well, we need to move the base disk (9) to C, so we move everything else off of it first, like this:

A 9
B 876543210
C

Then we can move disk 9

A
B 876543210
C 9

And then move the stack of nine disks back on to disk 9 to end up like this:

A
B
C 9876543210

Of course, I'm skipping the whole section of how to move the stack of nine disks, but this gives you the basic idea - moving a stack requires moving all but the bottom disk out of the way, then moving the bottom disk, then moving the rest of the disks back on top of it.

So this code is asking "Where are we in this process?" If k is equal to 2^(n-1), then we are currently moving the bottom disk of the stack that we are currently trying to move. If k is less than that, we are still in the middle of moving the stack of disks off of the bottom disk. If k is greater than that, we are trying to move the stack of disks back onto the bottom disk. Using my simple example above, if k = 2^(10-1) = 2 ^ 9 = 512, then we are moving disk 9 from A to C. if k is less than 512, then we are still in the process of moving disks 0 through 8 off of disk 9 and into spot B. If k is greater than 512, then we are at k -512 moves into moving disks 0 through 8 from spot B back onto disk 9 in spot C.

How do we know that 2^(n-1) is the correct value to use? Using mathematical induction we can prove that it takes at most (2^n)-1 moves to move a stack of n disks. Here is a quick proof:

Basis for induction: To move a stack of n=1 disks, it takes (2^n)-1=(2^1)-1=1 move - move the only disk. Inductive step: Assume that it works for n disks (ie that the most efficient way to move the stack takes (2^n)-1 moves). Then, to move a stack of n+1 disks, we first use the most efficient way to move the top n disks from off the bottom disk (taking (2^n)-1 moves), move the bottom disk (1 move), then move the other n disks back on top of the bottom disk ((2^n)-1 moves again). So the total number of moves we have taken is (2^n)-1+1+(2^n)-1=2*(2^n)-1=(2^(n+1))-1 moves.

If you haven't seen induction before this probably looks very complicated, but the basic idea is this - since we know it works for one disk, we know it works for two disks. Since we now know it works for two disks, it works for three disks. Since we now know it works for three disks... and so on. The inductive step was for an arbitrary n, so we can apply it as many times as we want. So for any finite n, we know that the fastest way to move the n disks takes (2^n)-1 moves.

So now the question is, on which move is the nth disk moved? On the (2^(n-1))-1-th move, we can finish moving the stack of n-1 disks on top of the bottom disk. Then, on the (2^(n-1))-1+1=2^(n-1)-th move, we are able to move the bottom disk.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM