• トップ
  • ブログ一覧
  • 【第1回】Brainfuckを実装しながら学ぶC++【Brainfuckとは】
  • 【第1回】Brainfuckを実装しながら学ぶC++【Brainfuckとは】

    メディアチームメディアチーム
    2020.12.08

    IT技術

    brainfuckを実装しながら学ぶC++

    第1回目~Brainfuckを実装しながらC++学ぼう

    本連載では、「Brainfuck」の特性を理解しながら、実際に Brainfuck インタプリタを作成していきたいと思います!

    実は、Brainfuck を理解するということは、C/C++ でつまずきがちな「ポインタの概念を理解する」ということにつながります。

    つまり、Brainfuck インタプリタの実装は、プログラミング言語を深く学習するのに、もってこいの題材だということ。

    今まで、C/C++ を避けていたプログラマの皆さん!

    これを機に、C/C++ をマスターしながら、Brainfuck もマスターしていきましょう!

    Brainfuckとは

    Brainfuck (またはBrainf*ck) は、実用性を無視した、難読プログラミング言語 (通称 Esolang ) に分類されます。

    単なるユーモアプログラミング言語でありながら、チューリング完全 (≒なんでもプログラミング可能) な言語でもあるのです。

    例えば、「Hello, world!」と出力させたければ、Brainfuck では以下のように記述します。

    1+++++++++[->++++++++>+++++++++++>+++++<<<]>.>++.+++++++..+++.>-.
    2------------.<++++++++.--------.+++.------.--------.>+.

    見た目は、何をしているのか、さっぱりですね…。

    にもかかわらず、やっていることは、大したことありません!(笑)

    Brainfuckの基本を学ぼう

    連載第1回目では、まずは Brainfuck の仕組みを理解していきましょう!

    Brainfuck には、8つの命令が存在します。

    Brainfuckの命令

    +ポインタの指す値を1加算する
    -ポインタの指す値を1減算する
    >ポインタを1つ進める
    <ポインタを1つ戻す
    [ループ始まり:ポインタの指す値が0ならば] を指すポインタの一つ先に移動
    ]ループ終わり:[ を指すポインタに移動
    .ポインタの値をASCIIコードで変換して出力
    ,入力を受け取る

    以上の8つの命令で、Brainfuck は成り立っているのです。

    これ以外は、全てコメントとみなされます。

    さて、ここで「ポインタ」という概念が出てきました。

    ポインタについて、簡単に説明します!

    ポインタ (Pointer)

    ポインタとは、その名の通り「指すもの」を表します。

    何を指しているかというと、メモリ番地です。

    プログラミングの世界では、変数や関数を読み取るとき、その内容をメモリに保存します。

    例えば、4バイト分のメモリを使用する整数型のint であれば、次のように保持されます。

    4バイト分のメモリを使用する整数型のintの表示

    これら変数にアクセスするときは、メモリ番地をもとに参照しますよね?

    そのメモリ番地を指すのが、ポインタです。

    この場合、変数num のポインタは「4」であり、「メモリ番地 4 」ということになります。

    そこに格納されている値が、「123 (=0x007b)」ということです (「0x」は16進数)。

    つまり、変数にアクセスしたときは、「まずはポインタで、メモリのどこに格納されているかを探し、その値を読み取る」というプロセスが起こっているわけですね!

    ちなみに Brainfuck では、ポインタの初期値は「0」で、値も全て「0」です。

    Brainfuckを実際に書いてみよう

    では次に、実際に書きながら理解しましょう。

    インタプリタは、WEBrainfuck のようなブラウザで動作するタイプでもいいですし、インタプリタをお手持ちの PC にインストールするタイプでも構いません。

    macOS であれば、

    1$ brew install brainfuck

    で、できます。

    Windows であれば、以下のリンクから、実行するでもいいでしょう。

    【BFI.exe】
    http://esoteric.sange.fi/brainfuck/compiled/win/BFI.exe

    とりあえず 「H」 を出力させる

    「Hello, world!」の前に、まずは一文字目の「H」を出力させてみましょう!

    「H」は、ASCII コードでは、10進数で「72」です。

    したがって、以下のようにポインタの指す値を「+」で72回インクリメントして、「.」で出力させれば良いのです。

    1++++++++++++++++++++
    2++++++++++++++++++++
    3++++++++++++++++++++
    4++++++++++++.

    これで「H」が出力されます。

    ...が、この調子で「Hello, world!」を出力させようとすると、まずそうな雰囲気が漂ってきますね(笑)

    そこで、[] の出番です。

    ループで綺麗に書く

    Brainfuck にも、Brainfuck らしい綺麗なコード、というものがあります。

    [ は、最初に解説したように、今ポインタが指している値が「0」であれば、] の一つ後へ飛ぶ命令。

    そして ] は、 [ に飛ぶ命令です。

    これを使って、スマートに「H」を出力してみましょう

    1++++++++++     # ループカウンタ
    2[->+++++++<]   # 7x10 = 70回インクリメント
    3>++.           # +2 して出力

    これでも「H」が出力されるはずです。

    記法はこの限りではありませんが、[] を使うだけで、Brainfuck らしいコードになります。

    このとき、0番地目のメモリはループカウンタ、1番地目のメモリは「H」の ASCII コードを保持しています。

    さらに細かく紐解くと、以下のような感じ。

    1++++++++++     # ループカウンタ
    2[
    3    ->         # ループカウンタを一つ減らしてポインタを右シフト
    4    +++++++    # +10
    5    <          # ポインタをループカウンタへ移動
    6]   
    7>++.           # +2 して出力

    ここまでくれば、あなたはもう Brainfucker ですね!

    Hello, world!

    それでは「Hello, world!」に挑戦しましょう。

    各 ASCII コードは以下になります。

    H72
    e101
    l108
    o111
    ,44
    [スペース]32
    w119
    r114
    d100
    !33

    メモリの使い方によって、実装方法はたくさんありますので、ここでは一例を示します。

    1++++++++++[->+++++++<]>++.     # 10 × 72 = 72
    2>++++++++++[->++++++++++<]>+.  # 10 × 101 = 101
    3<+++[->++<]>+.                 # 1013 × 21 = 108
    4.                              # 108
    5+++.                           # 1083 = 111
    6<<<++++[->-------<]>.          # 724 × 7 = 44
    7<+++[->----<]>.                # 442 × 4 = 32
    8>++[->++++<]>.                 # 1112 × 4 = 119
    9<++[->----<]>.                 # 1112 × 4 = 111
    10+++.                           # 1113 = 114
    11<++[->---<]>.                  # 1142 × 3 = 108
    12<++[->----<]>.                 # 1082 × 4 = 100
    13<<+.                           # 321 = 33

    冒頭の例とは違った例で、できるだけループを使うようにしてみました。

    ちなみに、コメントの+ーは、わざと全角にしています。

    1行につき一文字です。

    これを改行なしで書くと、さらに Brainfuck 感が出ますね(笑)

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

    次回からはBrainfuckのインタプリタを作る

    さて、Brainfuck の仕組みがわかったところで、いよいよ Brainfuck をデコードするインタプリタを作ってみましょう!

    ポインタを扱うには、C/C++ が最適ですので、C/C++ の知識も同時に身につけていきます。

    今回は、実装する前の予備知識として、Brainfuck を解説しました。

    次回からは、いよいよ C/C++ を使って、インタプリタの実装をしていきます。

    本連載では、今まで C/C++ を触ったことがないような人にも、理解できるような内容になっているので安心してくださいね!

    それでは、次回をお楽しみに!

    第2回はこちら!

    【第2回】Brainfuckを実装しながら学ぶC++【実装してみよう!前編】2020.12.15【第2回】Brainfuckを実装しながら学ぶC++【実装してみよう!前編】第2回~Brainfuckを実装しながら学ぶC++連載「Brainfuckを実装しながら学ぶC++」シリーズの第2回目...

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
    featureImg2020.07.27IT・コンピューターの歴史特集IT・コンピューターの歴史をまとめていきたいと思います!弊社ブログにある記事のみで構成しているため、まだ「未完成状態」...

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    メディアチーム
    メディアチーム
    Show more...

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background