teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

4

画像を追加

2019/06/02 07:24

投稿

xebme
xebme

スコア1109

answer CHANGED
@@ -114,4 +114,6 @@
114
114
 
115
115
  メソッド呼び出しの都度、異なる引数の値がコピーされるため異なる動作ができるのです。
116
116
 
117
- 再帰呼出はループではありませんが、再帰呼出することはループの繰り返しと同じことをしています。再帰呼出ししなければループ終了させるこになります。hanoi()では n=1 の時再帰しません。
117
+ 再帰呼出はループではありませんが、再帰呼出することはループの繰り返しと同じことをします。再帰呼出ししなければループ終了と同じ。hanoi()では n=1 の時再帰しません。
118
+
119
+ ![イメージ説明](40aa2067aa648a7c3202a1f7e9b15053.png)

3

再帰呼出の解説

2019/06/02 07:24

投稿

xebme
xebme

スコア1109

answer CHANGED
@@ -98,4 +98,20 @@
98
98
  hanoi(2, C, B, A) : return
99
99
  hanoi(3, A, B, C) : return
100
100
  => nil
101
- ```
101
+ ```
102
+
103
+ ### 追記(再帰呼出の解説)
104
+
105
+ ** 再帰呼出の動作**
106
+
107
+ 再帰呼出しとはメソッド(hanoi)の中から自分自身(hanoi)を呼ぶことです。これは、自分自身を呼ぶことを除けば、普通のメソッド呼出しと同じです。メソッド呼出しの動作は以下のとおり。
108
+ - def hanoiの(…)の括弧の中に記述されているのが引数です。n, from, to, viaです。
109
+ - 引数に値を設定(代入)してメソッドに渡すと引数のコピーが作られます。
110
+ 呼ばれたメソッドはコピーの値しか見えません。
111
+ - 呼ばれたメソッドは引数の値を使って処理を実行します。
112
+ hanoi()では原則に従い n=1 かそれ以外 (n≠1) かで処理が異なります。
113
+ - 処理が終わってメソッドからリターンする時に引数のコピーは消滅します。
114
+
115
+ メソッド呼び出しの都度、異なる引数の値がコピーされるため異なる動作ができるのです。
116
+
117
+ 再帰呼出はループではありませんが、再帰呼出することはループの繰り返しと同じことをしています。再帰呼出ししなければループを終了させることになります。hanoi()では n=1 の時再帰しません。

2

再帰呼出の理解

2019/06/02 04:16

投稿

xebme
xebme

スコア1109

answer CHANGED
@@ -46,4 +46,56 @@
46
46
  - 3) n-1 ピラミッドは、C->B へ移動
47
47
 
48
48
  **再帰の意味**
49
- 再帰するのは、問題を小さな部分問題に分割して解くためです。再帰する都度、n, n-1, n-2, ... , 1 と問題が小さくなり、1 のとき再帰せずリターンします。ネストした再帰がすべてリターンすると、部分問題がすべて解かれ、問題全体が解かれたことになります。再帰の動作がわかりづらければシーケンス図を書きましょう。表でもよい。縦に処理の流れ、横に再帰のネストごとの処理を畫いてください。
49
+ 再帰するのは、問題を小さな部分問題に分割して解くためです。再帰する都度、n, n-1, n-2, ... , 1 と問題が小さくなり、1 のとき再帰せずリターンします。ネストした再帰がすべてリターンすると、部分問題がすべて解かれ、問題全体が解かれたことになります。再帰の動作がわかりづらければシーケンス図を書きましょう。表でもよい。縦に処理の流れ、横に再帰のネストごとの処理を畫いてください。
50
+
51
+ ### 追記(再帰呼出のトレース)
52
+ > hanoi(n - 1, C, B, A)でいいと思うのですがこのメソッドの処理過程が真下に書いてないので混乱してます
53
+
54
+ コメントの内容から「ハノイの塔」の問題ではなく、それ以前の「再帰呼出し」が理解できていないと判断しました。トレースコードを示します。再帰を勉強してください。
55
+
56
+ **再帰呼出トレース用コード**
57
+ hanoi() の呼出/リターンを表示するための行を追加。
58
+
59
+ ```ruby
60
+ def hanoi(n, from, to, via)
61
+ puts "hanoi(#{n}, #{from}, #{to}, #{via}) : enter"
62
+ if n == 1
63
+ puts "#{from} から #{to} へ移す"
64
+ else
65
+ hanoi(n - 1, from, via, to)
66
+ puts "#{from} から #{to} へ移す"
67
+ hanoi(n - 1, via, to, from)
68
+ end
69
+ puts "hanoi(#{n}, #{from}, #{to}, #{via}) : return"
70
+ end
71
+
72
+ hanoi(3, :A, :B, :C)
73
+ ```
74
+
75
+ **再帰呼出トレース**
76
+ irbで実行した結果を編集しました。
77
+
78
+ ```irb
79
+ hanoi(3, A, B, C) : enter
80
+ hanoi(2, A, C, B) : enter <-- 前半の移動 (A->C)
81
+ hanoi(1, A, B, C) : enter
82
+ A から B へ移す <-- この円盤は、この下で B->C に移動する
83
+ hanoi(1, A, B, C) : return
84
+ A から C へ移す <-- 2) 2枚目(前半(n-1)最後の円盤)の移動
85
+ hanoi(1, B, C, A) : enter
86
+ B から C へ移す
87
+ hanoi(1, B, C, A) : return
88
+ hanoi(2, A, C, B) : return
89
+ A から B へ移す <-- 1) 3枚目(全体(n)最後の円盤)の移動
90
+ hanoi(2, C, B, A) : enter <-- 後半の移動 (C->B)
91
+ hanoi(1, C, A, B) : enter
92
+ C から A へ移す <-- この円盤は、この下で A->B に移動する
93
+ hanoi(1, C, A, B) : return
94
+ C から B へ移す <-- 3) 2枚目(後半(n-1)最後の円盤)の移動
95
+ hanoi(1, A, B, C) : enter
96
+ A から B へ移す
97
+ hanoi(1, A, B, C) : return
98
+ hanoi(2, C, B, A) : return
99
+ hanoi(3, A, B, C) : return
100
+ => nil
101
+ ```

1

追記。

2019/05/31 09:53

投稿

xebme
xebme

スコア1109

answer CHANGED
@@ -35,4 +35,15 @@
35
35
  LISPを使うハノイの塔プログラムの紹介。円盤 3枚の解説も載っているので立ち読みしてください。
36
36
 
37
37
  『コンピュータの数学』 ロナルド・L. グレアム、オーレン パタシュニク、ドナルド・E. クヌース 1993 共立出版
38
- 第1ページにハノイの塔の計算量の漸化式の解説があります。
38
+ 第1ページにハノイの塔の計算量の漸化式の解説があります。
39
+
40
+ ### 追記
41
+
42
+ **表示からわかること**
43
+ 中点にあたる移送を見れば、ピラミッドがどこに移動するのかが、わかります。
44
+ - 1) n ピラミッドは、A->B へ移動
45
+ - 2) n-1 ピラミッドは、A->C へ移動
46
+ - 3) n-1 ピラミッドは、C->B へ移動
47
+
48
+ **再帰の意味**
49
+ 再帰するのは、問題を小さな部分問題に分割して解くためです。再帰する都度、n, n-1, n-2, ... , 1 と問題が小さくなり、1 のとき再帰せずリターンします。ネストした再帰がすべてリターンすると、部分問題がすべて解かれ、問題全体が解かれたことになります。再帰の動作がわかりづらければシーケンス図を書きましょう。表でもよい。縦に処理の流れ、横に再帰のネストごとの処理を畫いてください。