Brainfuck入門:最もミニマルな難解プログラミング言語の世界へようこそ!🧠💥

プログラミング

たった8つの命令で全てを操る、驚異のシンプルさ

Brainfuckって何? 🤔

Brainfuck(ブレインファック)は、プログラミング言語の一種です。しかし、普通のプログラミング言語とは一味違います。これは「難解プログラミング言語」(Esoteric programming language、略してEsolang)と呼ばれるカテゴリーに属します。

難解プログラミング言語は、実用性を追求するのではなく、プログラミング言語の概念を探求したり、パズルとして楽しんだり、あるいはプログラマーを困惑させたり🤯するために作られます。Brainfuckはその中でも特に有名で、代表的な存在です。

その最大の特徴は、たった8種類の命令しか持たないことです。これらの命令を組み合わせて、あらゆる計算(理論上は)を行うことができます。この性質を「チューリング完全」と言います。

名前の「fuck」が卑語であるため、しばしば「Brainf*ck」や「Brainf**k」、「BF」などと伏せ字で表記されることもあります。

Brainfuckの歴史 📜

Brainfuckは、1993年にスイスの学生であったUrban Müller(ウアーバン・ミュラー)氏によって開発されました。

Müller氏の目標は、可能な限り小さなコンパイラを作成できるプログラミング言語を作ることでした。彼は当時存在した「FALSE」という言語(そのコンパイラは1024バイト)に触発され、さらに小さなものを目指しました。

その結果、Müller氏がAmiga(当時のコンピューター)向けにアセンブリ言語で作成したBrainfuckのコンパイラはわずか240バイト(情報源によっては123バイトとも)、インタプリタに至っては98バイトという驚異的な小ささを実現しました。

Brainfuckはその極端なシンプルさと難解さから、多くのプログラマーに衝撃と(ある種の)楽しみを与え、その後、Ook!(オランウータン語!?)やWhitespace(空白文字だけで記述!)など、多くの派生言語を生み出すきっかけとなりました。

Brainfuckの仕組み:メモリとポインタ 💾👉

Brainfuckのプログラムを理解するには、まずその動作モデルを知る必要があります。これは非常にシンプルです。

  1. メモリ配列(テープ): 非常に長い(慣習的に少なくとも30,000個の)メモリセル(箱)が一次元に並んでいます。各セルは1バイト(0から255までの整数)を記憶でき、最初はすべて0で初期化されています。
  2. データポインタ: メモリ配列の「現在位置」を示す矢印のようなものです。最初は一番左(0番目)のセルを指しています。
  3. 命令ポインタ: プログラムコード(後述の8つの命令)のどこを実行しているかを示すポインタです。
  4. 入力ストリーム: キーボードなどからの入力を受け取る流れです。
  5. 出力ストリーム: 画面などへ文字を出力する流れです。

Brainfuckのプログラムは、このデータポインタを左右に動かしたり、ポインタが指すセルの値を増やしたり減らしたり、値を入出力したりすることで動作します。

たった8つの命令! 🛠️

Brainfuckのプログラムは、以下の8つの記号(命令)のみで構成されます。これ以外の文字(アルファベット、数字、改行、スペースなど)はすべて無視され、コメントとして扱われます。

命令 動作 C言語での類似表現 (ptrはデータポインタ)
> データポインタを1つ右に移動する。 ptr++;
< データポインタを1つ左に移動する。 ptr--;
+ ポインタが指すセルの値を1増やす(インクリメント)。(255の次は0になる場合が多い) (*ptr)++;
ポインタが指すセルの値を1減らす(デクリメント)。(0の前は255になる場合が多い) (*ptr)--;
. ポインタが指すセルの値をASCIIコードと解釈し、対応する文字を出力する。 putchar(*ptr);
, 入力から1バイト読み込み、ポインタが指すセルにその値(ASCIIコード)を格納する。 *ptr = getchar();
[ ポインタが指すセルの値が0なら、対応する ] の直後までジャンプする。 while (*ptr) {
] ポインタが指すセルの値が0でないなら、対応する [ の直後までジャンプ(戻る)。 }

[] はセットで使い、ループ(繰り返し処理)を実現します。C言語などの while ループに似ています。

Brainfuckプログラミング例 💻

例1: 簡単な足し算 (2 + 3 = 5)

メモリを使って簡単な計算をしてみましょう。セル0に2を、セル1に3をセットし、それらを足してセル2に結果の5を格納し、最後に出力する例です。(ここでは数値そのものではなく、ASCIIコードで’5’を出力します)

++       セル0に2をセット (セル0 = 2)
>        ポインタをセル1へ移動
+++      セル1に3をセット (セル1 = 3)
[        セル1の値が0になるまでループ開始
  <+     ポインタをセル0へ移動し、値をインクリメント
  >-     ポインタをセル1へ戻し、値をデクリメント
]        ループ終了(この時点でセル0 = 2+3=5, セル1 = 0)
<        ポインタをセル0へ移動
+++++ +++++ +++++ +++++ +++++ +++   '0'のASCIIコード (48) を足す (セル0 = 5 + 48 = 53)
.        セル0の値 (53) をASCII文字 '5' として出力

(注意:このコードは、数値の5を出力するのではなく、文字としての’5’(ASCIIコード 53)を出力します。Brainfuckの . 命令はASCIIコードとして解釈するためです。)

例2: Hello World! 👋🌍

プログラミング入門の定番、「Hello World!」を出力するコードです。Brainfuckでは非常に長くなりがちですが、これは比較的よく知られた例の一つです。

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

このコードの動作を細かく追うのは大変ですが、基本的には +- で目標の文字のASCIIコードを作り、. で出力する、という作業を繰り返しています。[ ] ループをうまく使って、効率的にASCIIコードを生成している点がポイントです。

例えば、最初の ++++++++[...>...] の部分で、ループを使ってメモリの各セルに ‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘ ‘, ‘W’, ‘o’, ‘r’, ‘l’, ‘d’, ‘!’ に近い値を効率的に設定しています。その後、>>. などでポインタを移動させながら、微調整(+-)を行い、. で一文字ずつ出力していきます。

(詳細な解説は WikipediaWikibooks なども参考になります。)

例3: 入力された文字をそのまま出力 (catプログラム) 🐈

入力された文字を読み取り、そのまま出力する簡単なプログラムです。EOF(End of File、入力の終わり)が来るまで繰り返します。

,[.,]
  1. , : 入力から1バイト読み込み、セル0に格納。EOFの場合、多くの処理系では0または-1(255)を格納します。
  2. [ : セル0の値が0(EOFの場合など)なら、対応する ] の後にジャンプして終了。
  3. . : セル0の値(読み込んだ文字のASCIIコード)を出力。
  4. , : 次の文字を入力から読み込み、セル0に格納。
  5. ] : セル0の値が0でなければ(EOFでなければ)、対応する [ の直後(つまり .)に戻る。

Brainfuckを学ぶコツとツール ✨

Brainfuckは難解ですが、そのシンプルさゆえに学ぶ面白さもあります。

  • ゆっくり始める: 最初は各命令の意味をしっかり理解し、短いコード(例えば一文字だけ出力するなど)から試してみましょう。
  • メモリとポインタを視覚化する: 頭の中だけでメモリの状態やポインタの位置を追うのは大変です。紙に書いたり、視覚化ツールを使ったりするのがおすすめです。
  • オンライン実行環境やデバッガを活用する: 自分でインタプリタをインストールするのも良いですが、Webブラウザ上で手軽に試せる実行環境や、ステップ実行で動作を確認できるデバッガがたくさんあります。これらを使うと、コードがどのように動いているか理解しやすくなります。
  • 他人のコードを読む: “Hello World!” だけでなく、簡単な計算やアルゴリズムを実装したコードを探して読んでみるのも勉強になります。(ただし、解読は困難な場合が多いです!)
  • ASCIIコード表と仲良くなる: . 命令はASCIIコードで文字を出力するため、ASCIIコード表が手元にあると便利です。
注意点: Brainfuckの処理系(インタプリタやコンパイラ)には、細かい挙動に違いがある場合があります。例えば、メモリセルのサイズ(8ビットかそれ以上か)、セルの値がオーバーフロー/アンダーフローしたときの挙動(0に戻るか、ラップアラウンドするか)、メモリ配列のサイズ(有限か無限か)、EOF(入力終了)の扱いなどが異なることがあります。

なぜBrainfuckを学ぶの? 🤔

Brainfuckは実用的なプログラミングには全く向きません。コードは読みにくく、書くのも大変で、デバッグは困難を極めます。

しかし、それでもBrainfuckを学ぶことにはいくつかの面白さや意義があります。

  • プログラミングの低レベルな概念の理解: メモリやポインタといった、コンピューターの基本的な動作原理に近い概念に直接触れることができます。C言語などでポインタに苦戦した人が、別の角度から理解を深めるきっかけになるかもしれません。
  • チューリング完全性の体感: たった8つの命令だけで、理論上はどんな計算も可能であるという「チューリング完全」の概念を実感できます。
  • 論理的思考力のトレーニング: 極限まで制限された命令セットで目的の処理を実現するには、創造性と論理的な思考力が鍛えられます。パズルを解くような面白さがあります。
  • プログラミングの多様性を知る: 世の中には実用性だけではない、様々な目的やアイデアを持ったプログラミング言語が存在することを知るきっかけになります。
  • 話のネタになる: 「Brainfuckっていう言語知ってる?」と話のネタにできるかもしれません 😉。

まとめ

Brainfuckは、1993年にUrban Müllerによって作られた、たった8つの命令しか持たない難解プログラミング言語です。その極端なシンプルさと裏腹のチューリング完全性、そして読解困難なコードは、多くのプログラマーにとって挑戦であり、一種のパズルでもあります。

実用性は皆無ですが、コンピューターの基本的な仕組みやプログラミング言語の奥深さに触れる良い機会を与えてくれます。もし興味が湧いたら、オンラインの実行環境などで、ぜひ “Hello World!” から試してみてください!きっとあなたの脳(Brain)もファック(Hack? 🤔)されることでしょう!

参考情報

コメント

タイトルとURLをコピーしました