ハノイの塔を解くメソッド

ハノイの塔の問題に戻ろう。

一見難しそうなハノイの塔も、再帰的手法を用いて 問題を分割すると簡単になる。

ハノイの塔の問題分割

まず初期状態を見る。

ハノイの塔(移動前)
Tower of Hanoi - start

Aに積み重なっている4つの円盤群を、規則に従い1枚ずつBに移したい。 このときに、

「もし私の知らないところで誰かが1から3をAからCに移動してくれれ ば楽だなあ。そしたら私は4番をBに移して、最後にその人に1から3をBに戻しても らえばおしまいだ」

という風に考える。つまり、ハノイの塔に慣れた人を連れて来て、 1から3をCに移動してもらう(下図)。

1-3 disc moved from A C

次に自分で、4をBに移動する(下図)。

disc 4 moved from A B

そして、もう一度達人を連れて来て1から3をBに移動してもらう。

1-4 all finished!

こんなムシのいい考え方でよいのだろうか。よいのである。 連れて来られた達人は次のように考える。

plan to move 1-3 from A to C

「1から3をAからCに動かせばいいのか。うーむ。 寝てる間に誰かが1から2をAからBに移動してくれれば楽だなあ。 そしたら私は3番をCに移して、最後にその人に1から2をCに 戻してもらえばおしまいだ」

このようにして、

を繰り返していくと、最終的に

となり、最後に頼まれた人は1枚だけ移動すればよくなり、 何も考えなくても移動できることになる。

Rubyプログラムへ

上記の考え方をRubyメソッドにしよう。

を受け取り、移動手順を解くメソッド hanoi を考える。 重要な部分をことばで書くと次のようになる。

# n    = 枚数
# from = 元の棒の名前
# to   = ゴールの棒の名前
# work = 一時的に利用してよい棒の名前
def hanoi(n, from, to, work)
  if 1枚か?
    「n番の円盤を from から to に移動しなさい」
    と表示する(かんたん)
  else			# 2枚以上の場合
    まず n-1 だけを誰かに頼んで、一時待避棒に動かしてもらう
    そして「n番の円盤を from から to に移動しなさい」と表示
    最後に n-1 を誰かに頼んで、一時待避棒から目的棒に動かしてもらう
  end
end

これを実際にRubyプログラムに直すと完成する。


本日の目次