質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

4075閲覧

C言語 ハノイの塔の説明

hogeee

総合スコア27

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2020/10/24 22:29

c

1#include <stdio.h> 2 3int count = 0; 4void move(int no, int x, int y){ 5 if (no > 1) 6 move(no - 1, x, 6 - x - y); 7 8 printf("[%d]を%d軸から%d軸へ移動\n", no, x, y); 9 count++; 10 11 if (no > 1) 12 move(no - 1, 6 - x - y, y); 13} 14 15int main(void) { 16 int n; 17 printf("円盤の枚数:"); 18 scanf("%d", &n); 19 20 move(n, 1, 3); 21 22 printf("%d回移動しました。\n", count); 23 return 0; 24}

上のコードはハノイの塔なのですが、この再帰を理解することができません。
本には「最も大きい円盤以外の円盤をグループとみなせば、円盤の枚数とは無関係に、まったく同じ手続きを実現できます。」と書いてありますが、漠然としていてよくわかりません。

どのように理解すればよいでしょうか?
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

「最も大きい円盤以外の円盤をグループとみなせば、円盤の枚数とは無関係に、まったく同じ手続きを実現できます。」

「n枚の円盤が積みあがったピラミッド」 を
「n-1枚の円盤が積みあがったピラミッド」が「最大円盤」の上に乗ったもの とみなせば、

「n枚の円盤が積みあがったピラミッド」を x から y に移すには
・「n-1枚の円盤が積みあがったピラミッド」を x から 6-x-y に移す
・「最大円盤」を x から y に移す
・「n-1枚の円盤が積みあがったピラミッド」を 6-x-y から y に移す

をやればいい。この手順を素直に実装すると

C

1void move(int no, int x, int y){ 2 3 // 「n-1枚の円盤が積みあがったピラミッド」を x から 6-x-y に移す 4 if (no > 1) 5 move(no - 1, x, 6 - x - y); 6 7 // 「最大円盤」を x から y に移す 8 printf("[%d]を%d軸から%d軸へ移動\n", no, x, y); 9 count++; 10 11 // 「n-1枚の円盤が積みあがったピラミッド」を 6-x-y から y に移す 12 if (no > 1) 13 move(no - 1, 6 - x - y, y); 14}

投稿2020/10/24 22:57

episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hogeee

2020/10/24 23:02

なるほど、printの部分を最大円盤をxからyに移すと考えればよいのですね! その視点で考えていませんでした! ありがとうございます!
episteme

2020/10/24 23:08

で、どこが「漠然としていて」よくわからなかったのでしょう?
hogeee

2020/10/24 23:26

関数内の処理をパーツとして考えたときに パーツ① move(no - 1, x, 6 - x - y); パーツ② printf("[%d]を%d軸から%d軸へ移動\n", no, x, y); パーツ③ move(no - 1, 6 - x - y, y); をなぜこの順番で組むとハノイの塔の関数が完成するのか。もっと言うとなぜパーツ①とパーツ②はこのように再帰させるのかがわかりません。
episteme

2020/10/24 23:31

え? わからないのにベストアンサーつけたんですか?
hogeee

2020/10/24 23:32

あと、このハノイの問題を自分で実装するときに、どういう思考回路でこの関数をくみ上げればよいのかまったくイメージできません。そこが一番悩んでいます。 「最も大きい円盤以外の円盤をグループとみなせば、円盤の枚数とは無関係に、まったく同じ手続きを実現できます。」の考え方はわかるのですが、いざコードに書こうとするとどこから書いていいのか、、、 再帰を使った実装というのが本当に難しいです。自分で処理を考えきれないという感じです。
hogeee

2020/10/24 23:35

>え? わからないのにベストアンサーつけたんですか? 例えると迷路の答えがわかった感じです。なのでベストアンサーをつけさせていただきました。 しかし、迷路の自力での解き方がわからないという感じです。
guest

0

書いてのとおりです。複数枚重なっている場合でも、いちばん下の1枚だけ別に考えれば、動かし方は以下のようになります。

  1. いちばん下の1枚以外を、動かしたい棒と別の棒に移動させる
  2. いちばん下の1枚を、目的の棒まで動かす
  3. いちばん下の1枚以外を、動かしたいちばん下の1枚の上に戻す

投稿2020/10/24 22:43

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問