0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ハノイの塔に再帰で挑む

Last updated at Posted at 2020-09-30

こんばんは。
いつも応援、有難うございます。

有識者の皆様の見解を色々と拝見しましたが、
なかなか難しかったです。
多分自分の理解能力の問題なので、しょうがない。

まずはやってみましょう。
2 個の円盤を左端から、右端に移動させてみます。
ここで、右端、中央、左端の表現が微妙なので、
数字を割り振ります。
左端:1 , 中央:2 , 右端:3 とします。
図1.PNG
しれっと書きましたが、
右図に動かした円盤と何処から何処に
動かしたか、補足しています。

前回の記事にある階乗を再帰で攻略しましたが
流用出来ないでしょうか?ちょっと眺めてみましょう。

cure.py
def test(n:int=3):
    if n>1:
        return n * test(n-1)
    else:
        return 1

やりたい事としては。。

2枚の円盤を 1 から 3 へ移動したいのですが、
1番の円盤を 1 から 2 へ移動させてから、
2番の円盤を 1 から 3 へ移動させて、
1番の円盤を 2 から 3 へ移動させます。

枚、番を n として共通にして、
x から y に移動させてみましょう。
繰り返しになりますが、以下イメージです。

2枚(n)の円盤を 1(x) から 3(y) へ移動したいのですが、
1番(n)の円盤を 1(x) から 2(y) へ移動させてから、
2番(n)の円盤を 1(x) から 3(y) へ移動させて、
1番(n)の円盤を 2(x) から 3(y) へ移動させます。

よって、def test(n , x , y) で始めたら良さそうです。

2枚(n)の円盤を 1(x) から 3(y) へ移動したいのですが、=> def test(n , x , y): 
1番(n)の円盤を 1(x) から 2(y) へ移動させてから、
2番(n)の円盤を 1(x) から 3(y) へ移動させて、
1番(n)の円盤を 2(x) から 3(y) へ移動させます。

次です。
test(2,1,3) から start したら、次は
test(1,1,2) を渡す構成にする必要があります。
test(1,1,?)
最後の ? はどうやって作りましょうか。
各軸をナンバリングしたのを思い出してください。
1 + 2 + 3 = 6 なので、6-x-y とすれば ? を表現できます。

2枚(n)の円盤を 1(x) から 3(y) へ移動したいのですが、=> def test(n , x , y): 
1番(n)の円盤を 1(x) から 2(y) へ移動させてから、  =>     test(n-1,x ,6-x-y)
2番(n)の円盤を 1(x) から 3(y) へ移動させて、
1番(n)の円盤を 2(x) から 3(y) へ移動させます。

上記のままだと n == 0 の状態が発生します。
0 枚の円盤? 0 番の円盤? ちょっと破綻しそうなので、
if 文で条件を付けましょう。n>1 とすれば、
n==0 の条件を回避できます。

2枚(n)の円盤を 1(x) から 3(y) へ移動したいのですが、=> def test(n , x , y): 
1番(n)の円盤を 1(x) から 2(y) へ移動させてから、  =>   if n>1:
                                  test(n-1,x ,6-x-y)

2番(n)の円盤を 1(x) から 3(y) へ移動させて、
1番(n)の円盤を 2(x) から 3(y) へ移動させます。

test(1,1,2) で代入して考えると、前述の構成だと
if n > 1 にはハマらないので pass.
その段階で "1番(n)の円盤を 1(x) から 2(y) へ移動" とprint を使って表示出来れば OK です。

2枚(n)の円盤を 1(x) から 3(y) へ移動したいのですが、=> def test(n , x , y): 
1番(n)の円盤を 1(x) から 2(y) へ移動させてから、  =>   if n>1:
                                    test(n-1,x ,6-x-y)
                                  print(f"{n}を{x}=>{y}へ")
2番(n)の円盤を 1(x) から 3(y) へ移動させて、
1番(n)の円盤を 2(x) から 3(y) へ移動させます。

ちょっと説明が難しいのですが、
test(1,1,2) は print(f"{1}を{1}=>{2}へ") とイコールになります。
それを抜けると、test(2,1,3) の時の print(f"{2}を{1}=>{3}へ") に
自動的につながります。
最後の "1番(n)の円盤を 2(x) から 3(y) へ移動" はどうしましょうか。
私はこんな風にしてみました。

test.py
def test(n,x,y):
    if n>1:
        test(n-1,x,6-x-y)
    print(f"{n}{x}=>{y}")
    if n>1:
        test(n-1,6-x-y,y)

うーん、解説するかは考え中です(笑)。

0
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?