4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TDU_データ科学・機械学習研究室Advent Calendar 2021

Day 3

BrainF**kはすばらしい

Last updated at Posted at 2021-12-02

1. BrainF**kとは

python, Java, C, C++, etc... この世には様々なプログラミング言語が存在しその目的も多種多様です.
そんな中で, BrainF**kはできるだけコンパイラのサイズを小さくするために作成されました.

本記事では, そんな素晴らしい言語であるBrainF**kについてその仕様からこの言語の長所を説明していく隊と思います.

2. どのような言語か?

驚くべきことにBrainF**kはたった8文字によって構成される言語です. さらにはたった8文字だけで一般的なプログラミング言語と同様にチューリング完全です.

BrainF**kはプログラムが動き出した状態で0に初期化された30000個のバイト配列とその先頭を指すポインタ(current pointer)を持っており, これらの配列の値とポインタが指す先を動かすことによって処理を行います.

そして, 実際にコードに使用される文字は以下の8文字です. 以下の状態の時にそれぞれの文字が処理されるときの動作を具体的に説明します.

               ↓ current pointer
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| idx |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  
| val |  0  | 101 |  0  |  0  |  0  |  0  |  0  |  0  
+-----+-----+-----+-----+-----+-----+-----+-----+-----+ ... 

+ (ポインタが指す要素の値をインクリメントする)

current pointerが指す値要素の値は101なのでインクリメントされた結果以下のような状態になります.

               ↓ current pointer
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| idx |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  
| val |  0  | 102 |  0  |  0  |  0  |  0  |  0  |  0  
+-----+-----+-----+-----+-----+-----+-----+-----+-----+ ... 

- (ポインタが指す要素の値をデクリメントする)

current pointerが指す値要素の値は101なのでデクリメントされた結果以下のような状態になります.

               ↓ current pointer
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| idx |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  
| val |  0  | 100 |  0  |  0  |  0  |  0  |  0  |  0  
+-----+-----+-----+-----+-----+-----+-----+-----+-----+ ... 

> (ポインタをインクリメントする)

current pointerは現在1番目の要素を指している為, インクリメントされ以下の状態になります.

                     ↓ current pointer
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| idx |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  
| val |  0  | 101 |  0  |  0  |  0  |  0  |  0  |  0  
+-----+-----+-----+-----+-----+-----+-----+-----+-----+ ... 

< (ポインタをデクリメントする)

current pointerは現在1番目の要素を指している為, デクリメントされ以下の状態になります.

         ↓ current pointer
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| idx |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  
| val |  0  | 101 |  0  |  0  |  0  |  0  |  0  |  0  
+-----+-----+-----+-----+-----+-----+-----+-----+-----+ ... 

. (current pointerが指す要素の値を出力する)

current pointerが指す要素は現在101であるため, asciiでそれに対応する文字(今回であれば'A'が出力されます)
出力をするのみなので配列に変化はありません.

, (current pointerが指す要素に入力する)

current pointerが指す要素に標準入力から入力された文字に対応するasciiコードを代入します. 標準入力から'Z'(asciiコードは132)が入力された場合には以下の状態になります.

               ↓ current pointer
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| idx |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  
| val |  0  | 132 |  0  |  0  |  0  |  0  |  0  |  0  
+-----+-----+-----+-----+-----+-----+-----+-----+-----+ ... 

[] (ループ処理)

  • [ (ポインタが指す要素の値が0なら対応する]にジャンプする)
  • ] (ポインタが指す要素の値が0でないなら対応する[に戻る)
>++++[<+++++>-]

例えば以上のようなコードがあったとすると,

  1. 1文字目でポンタがインクリメントされcurrent pointerがidx=2に移動します.
  2. idx=2の値を4回インクリメントした後にループ処理に入ります.
  3. ループ処理では以下の処理を繰り返します.
    3-1. idx=1にもどる.
    3-2. idx=1の値5回インクリメントする.
    3-3. idx=2に進み要素の値をデクリメントする.
    3-4. 値が0であれば処理を終了し, そうでなければ3-1に戻る.

結果として5回のインクリメントを4回行うのでidx=1の値は20増え以下の状態になります.

               ↓ current pointer
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| idx |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  
| val |  0  | 121 |  0  |  0  |  0  |  0  |  0  |  0  
+-----+-----+-----+-----+-----+-----+-----+-----+-----+ ... 

3. BrainF**kのすばらしさ

以上でBrainF**kの大まかな説明は終了しました.
ここからは, その素晴らしさを説明していきます.

主なメリットは以下の3点です.

1. 覚えることが少ない

初学者がC言語を覚えようと思えばポインタの制御, 動的メモリの管理, データの集約管理方法, ... など覚えるべきことは無数に存在し一つのプログラムを完成させる前に挫折してしまうことも少なくありません.
その点, BrainF**kはその8文字で構成されるという特性から覚えることが極端に少ないです. たった8文字と配列の存在さえ覚えてしまえば終了です.

以上のことから, BrainF**kは学習コストが他の言語に比べて非常に低いことが分かります.

2. コードが簡潔に書ける(場合がある)

bash等のshellでcatコマンドを引数を渡さずに実行した場合以下のようにオウム返しを行う動作になります.

$> cat
hello(ユーザーが入力)
hello(標準出力)
(ユーザーの入力待機)

このような動作を行うコマンドを実装しようとすると, 以下のようなコードが書けるかと思います. (scanfが危険であるということは一度置いておいて)

#include <stdio.h>

int main(void)
{
  char buf[1024];

  while (1)
  {
    scanf("%s", buf);
    printf("%s\n", buf);
  }
  return (0);
}

では, Brainf**kで実装するとどのようになるでしょうか?

,[.,]

以上です.

C言語が130バイトを要していたにも関わらず, BrainF**kではわずか5バイトで実装することができました.
コードの簡潔さというのはコードを書く時も, 読むときも非常に重要な要素です. それをここまで短く簡潔に書ける(場合がある)というのはBrainF**kの大きな長所として挙げられるのではないでしょうか?

3. インタプリタを簡単に作ることができる

プログラムを制作する上で欠かせないのがインタプリタやコンパイラの存在です. これらがなければプログラムはただのテキストファイルに過ぎません. プログラミングの学習をしている際に一度はインタプリタを自作してみたいと思った方も多いのではないでしょうか. しかしながら, インタプリタの自作というのは容易ではありません. 通常の言語では仕様が膨大な量になり, とても気軽に作成できませんがBrainF**kではその仕様の少なさからプログラミングの経験者であれば1日以下でインタプリタを自作することができます.

また, インタプリタが作りやすいということはただ知的欲求を満たすだけではなく様々なシステムに組み込みやすいという実用的な面も存在します. 例えば, UnityでBrainF**kを元ネタにしたゲームを作るなど ( BrainHack ). 「アイデアが出ないがこのシステム/ツールを使ってとりあえず何かを作ってみたい」という時には丁度いいテーマになるのではないかと思います.

4. おわりに

ここまで散々BrainF**kを褒めてきましたが, 可読性などの面から実用性は皆無といっていいと思います.
しかし, 素晴らしさの3で挙げたインタプリタを自作できるということはインタプリタ型言語のプログラミングを学習する上でインタプリタの役割を実際に体感するという意味で, 非常に大きなメリットになるのではないかと思います.

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?