var | desc |
---|---|
Number of disks |
There are two rules in the game Tower of Hanoi:
- On each move we can only move the uppermost disk from a stack to another stack.
- It is not allowed to place a larger disk on a smaller disk.
For
Steps | ||
---|---|---|
Tower of Hanoi in context of programming is a classical example of recursive programming.
We have three stacks, let's call them src
for source, tmp
for temporary and tgt
for target. The goal is to move all disks from src
to tgt
in increasing order.
In the simplest case src
to tgt
. In this case the output of our program is:
1
1 3
The minimum steps required to win the game is to put the disk from stack 1 to stack 3.
Let's consider src
. We can only move one disk at a time.
- Take the smaller top disk in
src
(1) and move it to the temporary stacktmp
(2). - Take the larger disk remaining in
src
(1) and move it totgt
(3). - Take the smaller disk in
tmp
(2) and move it totgt
(3).
The output of the program should look like this:
3
1 2
1 3
2 3
Let's consider src
where
- Take
$d_1$ fromsrc
(1) and move it totgt
(3). - Take
$d_2$ fromsrc
(1) and move it totmp
(2). - Take
$d_1$ fromtgt
(3) and move it totmp
(2). - Take
$d_3$ fromsrc
(1) and move it totgt
(3). - Take
$d_1$ fromtmp
(2) and move it tosrc
(1). - Take
$d_2$ fromtmp
(2) and move it totgt
(3). - Take
$d_1$ fromsrc
(1) and move it totgt
(3).
As you can see we needed seven steps to complete the game. Here is the output:
7
1 3
1 2
3 2
1 3
2 1
2 3
1 3
We can observe that we basically do the same for any number of disks tmp
then moving the remaining largest disk in src
to tgt
. Then we use src
as temporary stack to move all temp
to tgt
. If there is only one disk remaining we move it directly to tgt
.
In Rust 🦀 code:
fn main() {
let n: u8 = std::io::read_to_string(std::io::stdin())
.unwrap()
.trim()
.parse()
.unwrap();
println!("{}", (0b1 << n) - 1);
hanoi(n, 1, 2, 3);
}
fn hanoi(n: u8, src: u8, tmp: u8, tgt: u8) {
if n == 0 { return; }
hanoi(n - 1, src, tgt, tmp);
println!("{} {}", src, tgt);
hanoi(n - 1, tmp, src, tgt);
}