Re-translate the Japanese version (#1871)

* Retranslate Japanese docs with GPT-5.4

* Retranslate Japanese code with GPT-5.4
This commit is contained in:
Yudong Jin
2026-03-30 07:30:15 +08:00
committed by GitHub
parent fe6443235b
commit d7b2277d2b
1444 changed files with 83312 additions and 8363 deletions
@@ -1,37 +1,37 @@
# ハノイの塔問題
# ハノイの塔問題
マージソート二分木構築の両方で、元の問題を2つの部分問題に分解し、それぞれが元の問題のサイズの半分でした。しかし、ハノイの塔では、異なる分解戦略を採用します。
マージソート二分木構築では、いずれも元の問題を元問題の半分の規模をもつ 2 つの部分問題に分解していました。しかし、ハノイの塔の問題では、異なる分解戦略を採用します。
!!! question
3の柱があり、それぞれ `A``B``C`表記されます。最初、柱 `A` $n$ 枚の円盤がり、上から下に向かって昇順のサイズで配置されています。私たちのタスクは、これらの $n$ 枚の円盤を柱 `C` に移し、元の順序を維持することです(以下の図に示すように)。移動中には以下のルールが適用されます
3の柱があり、それぞれ `A``B``C`します。初期状態では、柱 `A` に $n$ 枚の円盤が通されており、上から下へ小さい順に並んでいます。私たちの課題は、この $n$ 枚の円盤を柱 `C` に移し、元の順序を保つことです(以下の図のとおり)。円盤を移動する際には、次のルールに従う必要があります
1. 円盤は 1 本の柱の頂上から取り出し、別の柱の頂上に置くことしかできません。
2. 1 回に移動できる円盤は 1 枚だけです。
3. 小さい円盤は常に大きい円盤の上になければなりません。
1. 円盤は柱の上部からのみ取り除くことができ、別の柱の上部に置く必要があります。
2. 一度に移動できるのは1枚の円盤のみです。
3. 小さい円盤は常に大きい円盤の上にある必要があります。
![ハノイの塔の問題の例](hanota_problem.assets/hanota_example.png)
![ハノイの塔の例](hanota_problem.assets/hanota_example.png)
**サイズ $i$ のハノイの塔問題を $f(i)$ と表記します**。例えば、$f(3)$ は3枚の円盤を柱 `A` から柱 `C` に移動することを表します。
**規模が $i$ のハノイの塔の問題を $f(i)$ と表します** 。たとえば $f(3)$ は、$3$ 枚の円盤を `A` から `C` へ移動するハノイの塔の問題を表します。
### 基本ケースを考える
以下の図に示すように、問題 $f(1)$(円盤が1枚のみ)については、`A` から `C` 直接移動できます。
以下の図に示すように、問題 $f(1)$ 、すなわち円盤が 1 枚だけの場合は、それを `A` から `C` 直接移動すれば済みます。
=== "<1>"
![サイズ1の問題の解](hanota_problem.assets/hanota_f1_step1.png)
![規模 1 の問題の解](hanota_problem.assets/hanota_f1_step1.png)
=== "<2>"
![hanota_f1_step2](hanota_problem.assets/hanota_f1_step2.png)
$f(2)$(円盤が2枚)については、**柱 `B` の助けを借りて小さい円盤大きい円盤の上に保つ**必要があります。以下の図に示すように:
以下の図に示すように、問題 $f(2)$ 、すなわち円盤が 2 枚ある場合は、**小さい円盤が常に大きい円盤の上にある条件を満たすため、`B` を借りて移動を行う必要があります**。
1. まず小さい円盤を `A` から `B` に移動します。
2. 次に大きい円盤を `A` から `C` に移動します。
3. 最後に小さい円盤を `B` から `C` に移動します。
1. まず上の小さい円盤を `A` から `B` へ移します。
2. 次に大きい円盤を `A` から `C` へ移します。
3. 最後に小さい円盤を `B` から `C` へ移します。
=== "<1>"
![サイズ2の問題の解](hanota_problem.assets/hanota_f2_step1.png)
![規模 2 の問題の解](hanota_problem.assets/hanota_f2_step1.png)
=== "<2>"
![hanota_f2_step2](hanota_problem.assets/hanota_f2_step2.png)
@@ -42,20 +42,20 @@ $f(2)$(円盤が2枚)については、**柱 `B` の助けを借りて小さ
=== "<4>"
![hanota_f2_step4](hanota_problem.assets/hanota_f2_step4.png)
$f(2)$ を解決する過程は次のように要約できます:**`B` の助けを借りて2枚の円盤を `A` から `C` に移動する**。ここで`C`ターゲット柱、`B`バッファ柱と呼びます。
問題 $f(2)$ を解く過程は、**2 枚の円盤を `B` を介して `A` から `C` へ移す**と要約できます。このとき`C`目標の柱、`B`補助の柱と呼びます。
### 部分問題の分解
### 部分問題の分解
問題 $f(3)$(つまり、円盤が3枚の場合)については、状況やや複雑になります。
問題 $f(3)$ 、すなわち円盤が 3 枚ある場合になると、状況やや複雑になります。
すでに $f(1)$ と $f(2)$ の解が分かっているので、分割統治の観点を採用し、**`A` の上の2枚の円盤を1つの単位として扱い**、以下の図に示すステップを実行できます。これにより、3枚の円盤を `A` から `C` に正常に移動できます。
$f(1)$ と $f(2)$ の解が既知なので、分割統治の観点から、**`A` の上部にある 2 枚の円盤をひとまとまりとみなして**、次の図の手順を実行できます。こうして 3 枚の円盤を `A` から `C` へ順調に移動できます。
1. `B`ターゲット柱、`C`バッファ柱として、2枚の円盤を `A` から `B` に移動します。
2. 残りの円盤を `A` から直接 `C` 移動します。
3. `C`ターゲット柱、`A`バッファ柱として、2枚の円盤を `B` から `C` に移動します。
1. `B`目標の柱、`C`補助の柱として、2 枚の円盤を `A` から `B` へ移します。
2. `A` に残った 1 枚の円盤を `A` から `C` へ直接移動します。
3. `C`目標の柱、`A`補助の柱として、2 枚の円盤を `B` から `C` へ移します。
=== "<1>"
![サイズ3の問題の解](hanota_problem.assets/hanota_f3_step1.png)
![規模 3 の問題の解](hanota_problem.assets/hanota_f3_step1.png)
=== "<2>"
![hanota_f3_step2](hanota_problem.assets/hanota_f3_step2.png)
@@ -66,32 +66,32 @@ $f(2)$ を解決する過程は次のように要約できます:**`B` の助
=== "<4>"
![hanota_f3_step4](hanota_problem.assets/hanota_f3_step4.png)
本質的に、**$f(3)$ を2つの $f(2)$ 部分問題と1つの $f(1)$ 部分問題に分解します**。これら3つの部分問題を順次解決することで、元の問題解決され、部分問題が独立しており、それらの解をマージできることを示しています。
本質的に、**問題 $f(3)$ を 2 つの部分問題 $f(2)$ と 1 つの部分問題 $f(1)$ に分けています** 。この 3 つの部分問題を順に解けば、元の問題解決されます。これは、部分問題が独立しており、解を組み合わせられることを示しています。
ここから、以下の図に示すハノイの塔の分割統治戦略を要約できます。元の問題 $f(n)$ を2つの部分問題 $f(n-1)$ と1つの部分問題 $f(1)$ に分割し、以下の順序でこれら3つの部分問題を解決します
ここまでで、次の図に示すハノイの塔の問題を解く分割統治戦略をまとめられます。元の問題 $f(n)$ を 2 つの部分問題 $f(n-1)$ と 1 つの部分問題 $f(1)$ に分け、次の順序でこの 3 つの部分問題を解ます
1. `C` をバッファとして使用し、$n-1$ 枚の円盤を `A` から `B` に移動します。
2. 残りの円盤を `A` から直接 `C` に移動します。
3. `A` をバッファとして使用し、$n-1$ 枚の円盤を `B` から `C` に移動します。
1. $n-1$ 枚の円盤を `C` を介して `A` から `B` へ移します。
2. 残り $1$ 枚の円盤を `A` から `C` へ直接移します。
3. $n-1$ 枚の円盤を `A` を介して `B` から `C` へ移します。
各 $f(n-1)$ 部分問題について、**同じ再帰分割を適用でき**最小の部分問題 $f(1)$ に到達するまで続けます。$f(1)$ は単一の移動のみが必要であることがすでに分かっているため、解決するのは簡単です。
この 2 つの部分問題 $f(n-1)$ は、**同じ方法で再帰的に分割できます**最小の部分問題 $f(1)$ に到達するまでこれを続けます。一方、$f(1)$ の解は既知であり、1 回の移動操作だけで済みます。
![ハノイの塔を解決するための分割統治戦略](hanota_problem.assets/hanota_divide_and_conquer.png)
![ハノイの塔の問題を解く分割統治戦略](hanota_problem.assets/hanota_divide_and_conquer.png)
### コード実装
### コード実装
コードでは、再帰関数 `dfs(i, src, buf, tar)` を定義します。これは`src` から上の $i$ 枚の円盤を`tar` に移動し、柱 `buf` をバッファとして使用します:
コードでは、再帰関数 `dfs(i, src, buf, tar)` を定義します。その役割は、`src`上部にある $i$ 枚の円盤を、補助の柱 `buf` を使って目標の柱 `tar` へ移動することです:
```src
[file]{hanota}-[class]{}-[func]{solve_hanota}
```
以下の図に示すように、ハノイの塔問題は高さ $n$ の再帰木として視覚化できます。各ノードは部分問題を表し、`dfs()` の呼び出しに対応します。**したがって時間計算量は $O(2^n)$、空間計算量は $O(n)$ です。**
以下の図に示すように、ハノイの塔問題は高さ $n$ の再帰木を形成し、各ノードは 1 つの部分問題、すなわち 1 つ起動された `dfs()` 関数に対応します。**したがって時間計算量は $O(2^n)$ 、空間計算量は $O(n)$** です。
![ハノイの塔の再帰木](hanota_problem.assets/hanota_recursive_tree.png)
![ハノイの塔の問題の再帰木](hanota_problem.assets/hanota_recursive_tree.png)
!!! quote
ハノイの塔は古代の伝説に由来します。古代インドの寺院で、僧侶たちは3本の高いダイヤモンドの柱と、異なるサイズの $64$ 枚の金の円盤を持っていました。彼らは、最後の円盤が正しく置かれたとき、世界が終わると信じていました。
ハノイの塔の問題は古い伝説に由来します。古代インドのある寺院で、僧侶たちは 3 本の高いダイヤモンドの柱と、$64$ 枚の大きさの異なる金の円盤を持っていました。僧侶たちは絶えず円盤を動かし、最後の 1 枚が正しく置かれた瞬間に世界が終わると信じていました。
しかし、僧侶たちが1秒に1枚の円盤を移動したとしても、約 $2^{64} \approx 1.84×10^{19}$ —約5850億年—かかり、宇宙の年齢の現在の推定をはるかに超えています。したがって、この伝説が真実であれば、世界の終わりについて心配する必要はおそらくないでしょう
しかし、たとえ僧侶たちが 1 秒に 1 回移動するとしても、合計でおよそ $2^{64} \approx 1.84×10^{19}$ 秒、約 $5850$ 億年が必要で、現在推定されている宇宙の年齢をはるかに上回ります。したがって、この伝説が本当だったとしても、世界の終わり心配する必要はなさそうです