回答編集履歴
4
画像を追加
answer
CHANGED
@@ -114,4 +114,6 @@
|
|
114
114
|
|
115
115
|
メソッド呼び出しの都度、異なる引数の値がコピーされるため異なる動作ができるのです。
|
116
116
|
|
117
|
-
再帰呼出はループではありませんが、再帰呼出することはループの繰り返しと同じことをし
|
117
|
+
再帰呼出はループではありませんが、再帰呼出することはループの繰り返しと同じことをします。再帰呼出ししなければループ終了と同じ。hanoi()では n=1 の時再帰しません。
|
118
|
+
|
119
|
+

|
3
再帰呼出の解説
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
再帰呼出の理解
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
追記。
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 のとき再帰せずリターンします。ネストした再帰がすべてリターンすると、部分問題がすべて解かれ、問題全体が解かれたことになります。再帰の動作がわかりづらければシーケンス図を書きましょう。表でもよい。縦に処理の流れ、横に再帰のネストごとの処理を畫いてください。
|