なぜ JavaScript と Python と Lisp が「同じこと」を計算できるのか? 答えは「チューリング完全」だから。
1936年、アラン・チューリングが論文『計算可能数について』で提示した抽象機械。無限のテープと読み書きヘッドと状態だけで、計算可能なすべての関数を表現できる。
📼 仮想チューリングマシン: 0と1を反転する
紫=ヘッド位置。1なら0に書き換え、0なら1に書き換え、右に移動
ある言語/システムが チューリングマシンと同じ計算能力を持つとき、それは「チューリング完全」と呼ばれる。すなわち、原理的に 計算可能なものは何でも計算できる。
JavaScript, Python, Java, C, Ruby, Rust, Go, Lisp, Haskell... ほぼすべての汎用言語。
驚くべきことに Excel関数(LET/LAMBDA以降)、Magic: The Gathering、PowerPointもチューリング完全。
正規表現(基本機能のみ)、SQL(基本機能のみ)、HTML(マークアップのみ)、CSS(一部議論あり)。これらは表現力に制限があるかわりに、解析しやすく安全。
つまり「言語選び」は 何ができるかではなく どう書きやすいか・どう速いか・誰が読めるかの選択である。
「あるプログラムが永遠にループするか、いつか止まるか」を判定するプログラムは 原理的に作れない。これは数学的に証明されている。
もし「Halt(P, x)」という、プログラム P と入力 x が停止するなら true を返す関数があったとする。次の意地悪なプログラムを考える:
function Naughty(p) {
if (Halt(p, p)) {
while(true) {} // 永遠ループ
} else {
return; // 即座に停止
}
}
Naughty(Naughty); // ← これは停止する?しない?
Naughty(Naughty) が 停止すると仮定 → Halt が true → 永遠ループ → 停止しない。矛盾。
Naughty(Naughty) が 停止しないと仮定 → Halt が false → 即座に停止。矛盾。
よって Halt は存在しない。Q.E.D.(証明終了)
同じ問題でも、アルゴリズムによって速度が 100万倍違う。Big-O はその違いを表す共通語。
意訳: 入力サイズ n が大きくなったとき、最終的に g(n) の定数倍以下に収まる。定数とサブ項は無視する。
| 記法 | 名前 | 例 | n=1000で | 評価 |
|---|---|---|---|---|
| O(1) | 定数時間 | 配列の要素アクセス | 1回 | 最速 |
| O(log n) | 対数時間 | 二分探索 | 約10回 | 優秀 |
| O(√n) | 平方根 | 素数判定の試し割り | 約32回 | 良い |
| O(n) | 線形時間 | 配列の全走査 | 1,000回 | 良い |
| O(n log n) | 準線形 | マージソート、クイックソート | 約10,000回 | 実用上限 |
| O(n²) | 二乗時間 | バブルソート、二重ループ | 1,000,000回 | 小データOK |
| O(n³) | 三乗時間 | 素朴な行列積 | 10⁹回 | 注意 |
| O(2ⁿ) | 指数時間 | 素朴なフィボナッチ、巡回セールスマン | 宇宙が終わる前に終わらない | 絶望 |
| O(n!) | 階乗時間 | すべての順列を試す | もっと絶望 | 死 |
for (let x of arr) {
if (x === target) return true;
}
return false;
n=10⁹なら数秒〜数分
let lo=0, hi=arr.length-1;
while(lo<=hi) {
const mid=(lo+hi)>>1;
if(arr[mid]===target) return true;
if(arr[mid]
n=10⁹でも30回程度
100万ドルの懸賞金がかかった、計算機科学最大の未解決問題。
多項式時間で解ける問題。ソート、最短経路、行列積など。「効率的に解ける」と同義。
多項式時間で検証できる問題。解を1つ示されたら正しさをすぐ確かめられる。
NP より難しいか同等以上の問題。多くは指数時間しか知られていない。
NPの中で最も難しい問題群。1つでも多項式時間で解ければ P=NP となり全問題解決。
これらは現実世界(物流、暗号、設計、スケジュール)に大量に存在。完全解は無理なので近似アルゴリズム・ヒューリスティック・SAT solverが活躍する。
名前を聞いたら反応できる必修アルゴリズム。Knuth『TAOCP』の入口。
同じことをやらせたとき、言語によって 100倍以上差が出る。Carmackの世界観。
| 言語 | 相対速度 | メモリ効率 | 備考 |
|---|---|---|---|
| Assembly | 1.0x(最速) | 最良 | 人間より速く書けない |
| C | 1.0x | 最良 | 事実上の基準 |
| C++ | 1.0x | 最良 | 抽象化のオーバーヘッドはほぼない |
| Rust | 1.0-1.1x | 最良 | 安全性とのトレードオフほぼゼロ |
| Zig | 1.0-1.1x | 最良 | Cと同等 |
| Fortran | 1.0x | 最良 | 数値計算ではC超えも |
| Go | 1.5-3x | 良 | GC込みでこの速度は驚異 |
| Java (JIT) | 1.5-3x | 中 | JIT最適化が効くとCに迫る |
| C# (.NET) | 1.5-3x | 中 | JavaとほぼTie |
| Swift | 1.2-2x | 良 | Cに近い |
| Kotlin (JVM) | 1.5-3x | 中 | Java同等 |
| JavaScript (V8) | 2-5x | 中 | JIT次第で速い |
| Julia | 1-2x | 良 | 科学計算ではCを超えることも |
| Lua (LuaJIT) | 1-3x | 良 | JIT版は驚異的 |
| OCaml | 1.5-3x | 良 | 関数型ながら高速 |
| Haskell | 2-5x | 中 | 遅延評価コスト |
| Erlang/Elixir | 10-30x | 中 | 並行性で勝負 |
| Python (CPython) | 30-100x | 悪 | 遅さが弱点だが書きやすさで補う |
| Ruby | 30-100x | 悪 | Pythonと同等 |
| PHP | 5-30x | 中 | PHP 8で大幅高速化 |
| R | 30-100x | 悪 | ベクトル化で実用速度 |
| Perl | 10-50x | 中 | |
| VBA | 50-200x | 悪 | Excel依存で遅い |
| Scratch | 1000x+ | 悪 | 速度より教育目的 |
※あくまで素朴な目安。実際は実装・最適化・問題内容で大きく変動。Pythonでも NumPy/PyTorch 経由なら C 速度。重要なのは 「ホットスポット」を見つけて適切な言語/ライブラリを使うこと。
C / C++ / Rust / Zig / Fortran
ゲームエンジン、HFT、OS、組み込み
Go / Java / Swift / Kotlin / C#
Webサーバー、モバイル、エンタープライズ
Python / Ruby / JavaScript
スクリプト、Webサービス、AI
Erlang / Elixir / Go
チャット、通信、ライブ配信
GoF (Gang of Four) パターン入門。再発見し続けてきた「形」の名前。