Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
実用 Brainf*ck プログラミング
KMC ID:prime
目次
● 自己紹介
● Brainf*ck とは
● 開発環境の入手
● 実践編 :Brainf*ck でのコーディング
● 番外編 :?????
自己紹介
● KMC ID:prime
● Twitter ID:@_primenumber ( そすう )
● 最近始めたはてなブログ :
– http://primenumber.hatenadiary.jp/
● 京都大学理学部一回生 数...
ところで
おわび
● タイムテーブルでは「実用 Brainf*ck プログラミング入門編」
となっていましたが , これは入門編ではありません
– 任意のプログラムが ( 頑張れば )Brainf*ck で書けるよう
なレベルまで解説します
● 時間いっ...
Brainf*ck とは
Brainf*ck とは
● コンパイラがなるべく簡潔になるように設計された言語 , わず
か 8 種類の記号のみでプログラミングする
≠ 人間が読み書きしづらいように設計された言語
● 実際 ,Brainf*ck の 8 個の命令記号は可読性...
Brainf*ck とは
● 最初に 0 で初期化された十分な長さの配列が与えられる .
● 最初に 0 番地を指しているポインタがあり , このポインタを通
してデータを読み書きする .
● 制御構文 [ と ] によって条件分岐やループがで...
Brainf*ck とは
● 命令記号は以下の八種類
– + ポインタの指す値をインクリメントする
– - ポインタの指す値をデクリメントする
– > ポインタをインクリメントする
– < ポインタをデクリメントする
– , 入力を 1byte...
Brainf*ck とは
● それぞれの命令は C 言語で概ね対応する構文がある
– + C 言語の (*pt)++; に対応
– - C 言語の (*pt)--; に対応
– > C 言語の pt++; に対応
– < C 言語の pt--;...
Brainf*ck とは
● 処理系依存の仕様がいくつかある
– 配列の長さ
● 使用量に合わせるものと固定長のものがある
● ここでは使用量に合わせる ( 実質無限長 ) とする
– 数値がオーバーフロー・アンダーフローするときの扱い
● そ...
Brainf*ck とは
● 処理系依存の仕様
– 入力が EOF に達したときの処理
● 落ちる
● それ以降ずっと 0 を返す
● 直前に読んだ文字と同じ文字を返し続ける
● そもそも入出力を標準入出力に繋げないのもあり
– シェルに繋げば...
Brainf*ck とは
番地 0 1 2 3 4 …
データ 0 0 0 0 0 …
+ > + < -
Brainf*ck とは
番地 0 1 2 3 4 …
データ 1 0 0 0 0 …
+ > + < -
Brainf*ck とは
番地 0 1 2 3 4 …
データ 1 0 0 0 0 …
+ > + < -
Brainf*ck とは
番地 0 1 2 3 4 …
データ 1 1 0 0 0 …
+ > + < -
Brainf*ck とは
番地 0 1 2 3 4 …
データ 1 1 0 0 0 …
+ > + < -
Brainf*ck とは
番地 0 1 2 3 4 …
データ 0 1 0 0 0 …
+ > + < -
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 0 0 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 0 0 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 0 0 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 0 0 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 65 0 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 65 0 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 65 0 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 65 66 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 65 66 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 65 66 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 65 66 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
番地 0 1 2 3 4 …
データ 64 65 66 0 0 …
. [ > , ]
入力 出力
'A' 'B' '0' '@'
Brainf*ck とは
● これだけの命令記号で ( 無限長の配列なら ) チューリング完全
– 他のプログラミング言語でできることなら ( 理論上 ) なんで
もできる
● 「でも実際に実装するのはほぼ無理でしょ ? 」
Brainf*ck とは
● これだけの命令記号で ( 無限長の配列なら ) チューリング完全
– 他のプログラミング言語でできることなら ( 理論上 ) なんで
もできる
● 「でも実際に実装するのはほぼ無理でしょ ? 」
– 実はある程度の...
Brainf*ck とは
● これだけの命令記号で ( 無限長の配列なら ) チューリング完全
– 他のプログラミング言語でできることなら ( 理論上 ) なんで
もできる
● 「でも実際に実装するのはほぼ無理でしょ ? 」
– 実はある程度の...
開発環境の入手
開発環境の入手
● ブラウザ上で実行できるインタプリタを用意しました
– http://moon.kmc.gr.jp/~prime/brainf_ck/env/
– デバッグを ON にすると今どこを処理しているかやメモリの内
容が可視化される...
開発環境の入手
● 最適化のかかるインタプリタを C++ で用意しました
– http://moon.kmc.gr.jp/~prime/brainf_ck/bfi.cpp
– C++11 でコンパイルしてください
● gcc/clang ならコ...
サンプルコードの入手
● 今日使うサンプルコードをおいておきます
– http://moon.kmc.gr.jp/~prime/brainf_ck/bftext/
– このページを常に開いておくことをおすすめします
● ASCII コード表もす...
● ここからいよいよ実際にどうコーディングするかを解説します
● 今回は「なるべく書きやすいコーディング方法」を紹介します
– その分コードが冗長になったり低速になったりします
– 入力が正しいかをチェックしません
– どうすればより短く , ...
入門編
入門編 :for ループ
● for ループ
– {0} の値の回数だけ *** という処理を行う
– コード )[***-]
– *** を行うたびに {0} の値を 1 減らす
– ! 注意 !*** の中で {0} の値を変更しないこと ...
入門編 : 初期化 , 代入
● 初期化
– {0} の値を 0 クリアする
– コード )[-]
– 0 になるまで 1 減らす , という操作を行う .
● 代入
– {0} に自分の好きな定数を代入する
– コード )[-]+++++++...
入門編 : 値の移動 , 足し算
● 値の移動
– {0} から {1} に値を移動する .
– 最初 {1} は 0 だったとする .
– コード )[>+<-]
– {1} の値を 1 増やし ,{0} の値を 1 減らす , ということを...
入門編 : 引き算 , 値のコピー
● 引き算
– {1} から {0} を引いた値を {1} に入れる
– コード )[>-<-]
– {1} と {0} を 1 減らすことを {0} が 0 になるまで繰り返す
● 値のコピー
● Brai...
入門編 : 掛け算
● 定数倍
– {0} の値の 5 倍を {1} に入れる
– コード )[>+++++<-]
● 掛け算
– {0} と {1} の積を {2} に入れる ({3} を一時変数として使
う )
– コード )[>[>+>+...
入門編 : 演習
● 数字二文字を入力にとってその和を出力する Brainf*ck コー
ドを書きましょう
● とりあえず次の条件で作ってみましょう
– 数字二文字 (ASCII コードで 48~57 が '0' から '9' に対
応 ) 以...
入門編 : 演習
● コード例
– ,>,>++++++[<-------->-]<<[>+<-]>.
– 幸いにも ASCII コードは小さい順に並んでいるの
で '0'=48 を引けば数値になる
入門編 : スタック
● スタックと Brainf*ck の命令体系は親和性が高い
– push が > に ,pop が < に対応している
– スタックに 3,2,3 を積み , その積を計算する
– コード )+++>++>+++>
<<...
入門編 : 再帰
● 再帰 : 関数からその関数自身を呼ぶこと
– 再帰を使うと処理が簡潔に書けるケースがたくさん知られ
ている
入門編 : 再帰
● 再帰 : 関数からその関数自身を呼ぶこと
– 再帰を使うと処理が簡潔に書けるケースがたくさん知られ
ている
● 実は再帰はスタックを用いて書ける
– 再帰関数の引数をスタックに積むことで実現する
入門編 : 再帰
● 再帰 : 関数からその関数自身を呼ぶこと
– 再帰を使うと処理が簡潔に書けるケースがたくさん知られ
ている
● 実は再帰はスタックを用いて書ける
– 再帰関数の引数をスタックに積むことで実現する
→Brainf*ck では...
入門編 : 再帰
● 再帰 : 関数からその関数自身を呼ぶこと
– 再帰を使うと処理が簡潔に書けるケースがたくさん知られ
ている
● 実は再帰はスタックを用いて書ける
– 再帰関数の引数をスタックに積むことで実現する
→Brainf*ck では...
入門編 : 再帰
● 再帰 : 関数からその関数自身を呼ぶこと
– 再帰を使うと処理が簡潔に書けるケースがたくさん知られ
ている
● 実は再帰はスタックを用いて書ける
– 再帰関数の引数をスタックに積むことで実現する
→Brainf*ck では...
ハノイの塔
● リュカという数学者が考案したと言われるパズルゲーム
● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左
端の棒に大きいものが下になるように置かれている
● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させ...
ハノイの塔
● リュカという数学者が考案したと言われるパズルゲーム
● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左
端の棒に大きいものが下になるように置かれている
● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させ...
ハノイの塔
● リュカという数学者が考案したと言われるパズルゲーム
● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左
端の棒に大きいものが下になるように置かれている
● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させ...
ハノイの塔
● リュカという数学者が考案したと言われるパズルゲーム
● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左
端の棒に大きいものが下になるように置かれている
● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させ...
ハノイの塔
● リュカという数学者が考案したと言われるパズルゲーム
● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左
端の棒に大きいものが下になるように置かれている
● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させ...
ハノイの塔
● リュカという数学者が考案したと言われるパズルゲーム
● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左
端の棒に大きいものが下になるように置かれている
● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させ...
ハノイの塔
● リュカという数学者が考案したと言われるパズルゲーム
● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左
端の棒に大きいものが下になるように置かれている
● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させ...
ハノイの塔
● リュカという数学者が考案したと言われるパズルゲーム
● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左
端の棒に大きいものが下になるように置かれている
● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させ...
ハノイの塔
● ハノイの塔は再帰的な手続きによって最短で解けることが知
られている
● 何らかの方法で左端の上から n-1 枚の円盤を真ん中の棒
に移動させる
● 左端にある一番大きな円盤を右端の棒に移動させる
● 何らかの方法で真ん中の棒の ...
Brainf*ck でハノイの塔
● ハノイの塔を解くプログラムを Brainf*ck で作っていく
● 具体的な動かし方を ' 円盤の名前 ' ' 動かす前の棒の番号
' ' 動かす先の棒の番号 ' の形で出力する
● 円盤には小さい方から ...
Brainf*ck でハノイの塔
● プログラムの動作を擬似コードで書く
Hanoi(n,a,b)//n 枚の円盤を a から b に動かす
Hanoi(n-1,a,c)
Move(n,a,b)
Hanoi(n-1,c,b)
end
● Mov...
Brainf*ck でハノイの塔
● c は 6-a-b で求められる ( 引き算だから簡単 !)
● Hanoi の中で Move という別の関数を呼ぶ処理は書きにくい
– よく見ると Hanoi と Move は引数の形が同じ
– 引数を一...
Brainf*ck でハノイの塔
①最初にスタックに (n,s,a,b)=(n,1,1,3) を積む
②スタックの一番上の値を読み、 s=0 なら 6 に飛ぶ
③スタックから取り出した値が (n,1,a,b) だったとすると
それを消してスタッ...
Brainf*ck でハノイの塔
● 実際のコード
>>>>++++>+>+>+++<<<[>[<-[[>>>>+>>>>+>>>>+<<<<<<<<<<<<-
]>[>>>>+>>>>+>>>>+<<<<<<<<<<<<-]>[>>>>+>>...
Brainf*ck でハノイの塔
● 見やすく整形すると
>>>>+>+++++[<+++++>-]+>+>+++<<<
[>[
<-[
[>>>>+>>>>+>>>>+<<<<<<<<<<<<-]
>[>>>>+>>>>+>>>>+<<<<<...
初級編
初級編 :if イディオム
● Brainf*ck には while 文に相当する [,] はあるが ,if 文に
相当する構文はない
● while 文のループを 1 回で終えれば if 文と同じ動作になる
– {0} が 0 でなければ *...
初級編 :if イディオム
● 二つの値が等しい・等しくないで分岐する
– {0}={1} なら *1* を , そうでないなら *0* を実行する
– コード )[>-<-]>>+<[*1*>-<[-]]>[*0*-]
– {1}-{0} を...
初級編 : 大小比較
● 大小比較
– {0}<{1} なら *0* を , そうでないなら *1* を実行 ( 一時変
数として {2},{3} を使用 )
– コード )
[>>>+<<[-<->[>+<-]>>-<<]>[<+>-]>[-...
初級編 : 除算
● 除算
– {0}÷{1} の商を {6} に , 余りを {7} に入れる ({2} 〜 {5}
を一時変数として使う )
– コード )
[[>>+>+<<<-]>>>[<<<+>>>-]<<[>>+>+<<<-]>>>...
初級編 : 配列
● ランダムアクセス出来る配列を実現したい
– 例 ) 配列の {0} 番目の値を参照する
● 次のようにデータを配置することで可能
● 2 バイトごとに一つの値を格納する (1 セクションと呼ぶことにする )
– 1 バイト...
初級編 : 配列
● 配列を走査したい
● 配列の端を求めたい
● 1 セクションを 3 バイト区切りにする
– 1 バイト目に値
– 2 バイト目に 1: 直前に値があることを示す
– 3 バイト目は計算領域
● 3n 番地から配列の終端まで...
初級編 : 配列
● 同様にして配列の先頭に飛ぶことも出来る
● セクションをひとつずつ移動し , そのセクションの 2 バイト目
が 1 の間 ~ する , というコードを書くことで配列を走査出来る
● この方法でデータを格納すると (256...
初級編 : 配列
● ポインタを使いたい ( 今居る場所を記憶して後で戻りたい )
– ひとつの配列にひとつのポインタであれば , ポインタの指
している区切りの 2 バイト目を 0 にすることで実現できる
– コード )[>>>]
– 3 番...
初級編 : 配列
● この場合のポインタというのは , 参照している場所を保存する
ためのデータ構造といえる
– アドレスを格納する変数を用意しようと思うと ,256 要素以
上の配列に対しては多倍長整数が扱える必要がある
● 多倍長整数を扱う...
初級編 : 配列
● 長さ {0} のポインタフラグ付き配列を作る ( 配列の最初の要素
が来るのは 3 番地 )
– コード )[>>>>[>>>]+[<<<]<-]
● ポインタフラグ付き配列のコピー
– 最初配列の先頭にポインタがあるもの...
Brainf*ck で Brainf*ck インタプリタ
● 初級編で取り上げた条件分岐や配列を使ったプログラムとし
て ,Brainf*ck で Brainf*ck のインタプリタを書いてみます
● 仕様
– Brainf*ck のソースコー...
Brainf*ck で Brainf*ck インタプリタ
● ソースコードとデータの配列は次のように配置する
● ck: ソースコードの k 文字目
● dk: 配列の k 番目の値
● pk,qk: プログラムポインタフラグ , データポイン...
Brainf*ck で Brainf*ck インタプリタ
①標準入力から ! が現れるまで読み込み , ソースコードを格納
する配列に格納する . プログラムポインタフラグは p1 を 0, それ
以外を 1 にする
②プログラムポインタの指す...
Brainf*ck で Brainf*ck インタプリタ
⑥(. の処理 ) データポインタまで飛び , 値を標準出力に出力
し , プログラムポインタまで戻る
⑦(< の処理 ) データポインタまで飛び , データポインタをひとつ
戻し , ...
Brainf*ck で Brainf*ck インタプリタ
⑫(] の処理 ) データポインタまで飛び , 値が 0 ならば⑭に飛ぶ
⑬プログラムポインタに飛び , ソースコードの配列をプログラム
ポインタを後退させながら戻っていき ,[ と ]...
Brainf*ck で Brainf*ck インタプリタ
● 実際のコード
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>...
Brainf*ck で Brainf*ck インタプリタ
● 分かるかボケ
– はい
Brainf*ck で Brainf*ck インタプリタ
● 分かるかボケ
– はい
– 全体を眺めていても何がなんだかわからないので部分ご
とに見て行きます
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
>>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<]
>>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<-...
Brainf*ck で Brainf*ck インタプリタ
● 部分部分に分解していけばこれまでにやったことの組み合わ
せでできる
● このインタプリタはめちゃくちゃ遅い
– 比較するのに何回もコピーをとっている
– データとソースコードを行った...
中級編
中級編
● ここから難易度がインフレ !!!!!
● いちいち細かい実装を見ていると終わらない
● おおまかにどうやって実装するか , どのくらいのコード量 , 計
算量 , メモリ消費になるかに絞って見ていく
中級編 : 多倍長整数
● さすがに数値が 255 までしか扱えないのは色々と不便
– 大きな整数 ( できればメモリの許す限り大きな数 ) を扱いたい
● 今回は比較的実装の楽な二つの実装を紹介
– 実装量はそこそこでそこそこの計算量
– 実...
中級編 : 多倍長整数
● 実装量はそこそこでそこそこの計算量になる実装
● 値を 2 進数のポインタ付き配列で保存し ,3 バイト区切り一つ
で 1 ビット格納する , 負の数は最上位 bit が 1 になる
– メモリ消費量は桁数に比例
●...
中級編 : 多倍長整数
● 足し算
– 2 数の配列は 0,0,0 でつないであり , ポインタは 2 数の直
後を指しているものとする , オーバーフローはないと仮定
– コード )
<<[-<[<<[<<<]<<<[<<<]<+>>>>[>...
中級編 : 多倍長整数
● 引き算
– コード )
<<[<<+>[<->-]<[>+<-]<]>>>[>>>]<<<[-<[<<[<<<]<<<[
<<<]<+>>>>[>>>]>>>[>>>]<-]<<[<<<]<<<[<<<]<<<[-]...
中級編 : 多倍長整数
● 掛け算(非破壊版 )
– コード )
[->>>[>>>]>>>[>>>]>>>[>>>]+>>>+[<<<]<<<[<<<]<<<[<<<]+>>>]<<<[<<<]>>><[>>>>[>>>]>
>>[>>>]>...
中級編 : 多倍長整数
● 掛け算
– まず ,2 つの数の符号を調べ , 積が正負どちらになるか保
存して ,2 つの数を正の数に直す
– 長さ 2n の配列を用意
– いわゆる筆算をする
●
– n 回足し算をしているが ,1 回足し算をす...
中級編 : 多倍長整数
● ( 実質的な ) 実装量は少ないが計算量はかなり大きい実装
● 2 進数でもめんどくさいのは繰り上がりがあるから
– 繰り上がりの問題を何とかしたい
中級編 : 多倍長整数
● ( 実質的な ) 実装量は少ないが計算量はかなり大きい実装
● 2 進数でもめんどくさいのは繰り上がりがあるから
– 繰り上がりの問題を何とかしたい
● !!!1 進数多倍長 !!!
● 1 進数なら繰り上がりは常に...
中級編 : 多倍長整数
● まずは自然数 (0 以上の整数 ) を表現する方法を考える
– 連続する 1 の個数で表現する
– 10 億を表すのに約 1GB のメモリを消費する
– それでも無限のメモリがあればどんなに大きな値も表せる
● 足し...
中級編 : 多倍長整数
● コピー
– [->[>]>[>]+[<]<[<]+>]
– 1 進数多倍長の計算はほとんどコピーの組み合わせ
● 足し算 ( 非破壊版 )
– コード )[->[>]>[>]>[>]+[<]<[<]<[<]+>]>[...
● 引き算 ( 片方が 0 になるまで )
– コード )
[[>]>[[>]>+<<[<]]<[<]]>[>]>[>]>[-<<-<[<]<[<]>->[
[>]>[[>]>+<<[<]]<[<]]>[>]>[>]>]
● 割り算 ( 非破壊...
中級編 : 多倍長整数
● 負の数も表現したい
● 符号を格納する領域を作っても良いが , 符号によって場合分
けが必要になり , 大変
● 2 つの自然数を組にして , その差として表現する
– (x,y) という組で x-y という整数を表...
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
Upcoming SlideShare
Loading in …5
×

実用Brainf*ckプログラミング

10,664 views

Published on

Brainf*ckで実用的なプログラムが書けるようになろう!というスライドです.
このスライドは関西情報系学生団体交流会の勉強会で用いたスライドを誤字訂正などの若干の修正を加えたものです.
勉強会の時間の都合上上級編はありません.
入門編:forループ,初期化,代入,値の移動,足し算,引き算,値のコピー,掛け算,スタック,再帰
初級編:ifイディオム,大小比較,割り算,配列
中級編:多倍長精度整数・多倍長精度浮動小数点数
番外編:Brainf*ckでメタプログラミング

Published in: Technology

実用Brainf*ckプログラミング

  1. 1. 実用 Brainf*ck プログラミング KMC ID:prime
  2. 2. 目次 ● 自己紹介 ● Brainf*ck とは ● 開発環境の入手 ● 実践編 :Brainf*ck でのコーディング ● 番外編 :?????
  3. 3. 自己紹介 ● KMC ID:prime ● Twitter ID:@_primenumber ( そすう ) ● 最近始めたはてなブログ : – http://primenumber.hatenadiary.jp/ ● 京都大学理学部一回生 数学系志望 ● 普段使う言語 :C++,Brainf*ck, たまに Ruby,Coq ● 競技プログラミング :Codeforces,AOJ,ICPC... ● 数学ぽいプログラミングもやってます – 素数判定・素数表作成・素因数分解 , フィボナッチ数 , コ ラッツ予想の検証 , 多項式ライブラリ , ・・・
  4. 4. ところで
  5. 5. おわび ● タイムテーブルでは「実用 Brainf*ck プログラミング入門編」 となっていましたが , これは入門編ではありません – 任意のプログラムが ( 頑張れば )Brainf*ck で書けるよう なレベルまで解説します ● 時間いっぱい参加者の皆さんを Brainf*ck でガンガン殴り続 ける予定です ● 入門編 , 初級編 , 中級編と進みます – 上級編もやりたいですが時間の都合上省略します
  6. 6. Brainf*ck とは
  7. 7. Brainf*ck とは ● コンパイラがなるべく簡潔になるように設計された言語 , わず か 8 種類の記号のみでプログラミングする ≠ 人間が読み書きしづらいように設計された言語 ● 実際 ,Brainf*ck の 8 個の命令記号は可読性が上がるよう に選ばれている ● 構造化プログラミングのエッセンスを抽出しているのが特徴 → 忌まわしき goto 文は存在しないため , スパゲッティー コード化が起こりにくい !!!!!
  8. 8. Brainf*ck とは ● 最初に 0 で初期化された十分な長さの配列が与えられる . ● 最初に 0 番地を指しているポインタがあり , このポインタを通 してデータを読み書きする . ● 制御構文 [ と ] によって条件分岐やループができる 番地 0 1 2 3 4 … データ 0 0 0 0 0 …
  9. 9. Brainf*ck とは ● 命令記号は以下の八種類 – + ポインタの指す値をインクリメントする – - ポインタの指す値をデクリメントする – > ポインタをインクリメントする – < ポインタをデクリメントする – , 入力を 1byte 読んでポインタの指す場所に代入する – . ポインタの指す値を文字として出力する – [ ポインタの指す値が 0 なら対応する ] に飛ぶ – ] ポインタの指す値が 0 以外なら対応する [ に飛ぶ
  10. 10. Brainf*ck とは ● それぞれの命令は C 言語で概ね対応する構文がある – + C 言語の (*pt)++; に対応 – - C 言語の (*pt)--; に対応 – > C 言語の pt++; に対応 – < C 言語の pt--; に対応 – , C 言語の *pt = getchar(); に対応 – . C 言語の putchar(*pt); に対応 – [ C 言語の while(*pt){ に対応 – ] C 言語の } に対応
  11. 11. Brainf*ck とは ● 処理系依存の仕様がいくつかある – 配列の長さ ● 使用量に合わせるものと固定長のものがある ● ここでは使用量に合わせる ( 実質無限長 ) とする – 数値がオーバーフロー・アンダーフローするときの扱い ● それ以上値が変化しないものと最大値 <-> 最小値と変 化するものがある ● ここでは 255<->0 となるものとします – 0 番地より左にポインタが移動したとき ● 実行時エラーを吐くもの , 負番地にもアクセスできるも の , 配列の反対側に回るものがある ● ここでは実行時エラーを吐くものとする
  12. 12. Brainf*ck とは ● 処理系依存の仕様 – 入力が EOF に達したときの処理 ● 落ちる ● それ以降ずっと 0 を返す ● 直前に読んだ文字と同じ文字を返し続ける ● そもそも入出力を標準入出力に繋げないのもあり – シェルに繋げばマシンが操作できる – オーディオ入出力に繋いでもよし , ディスプレイ出力に繋 いでもよし – とりあえず今回は標準入出力につなぐことにします
  13. 13. Brainf*ck とは 番地 0 1 2 3 4 … データ 0 0 0 0 0 … + > + < -
  14. 14. Brainf*ck とは 番地 0 1 2 3 4 … データ 1 0 0 0 0 … + > + < -
  15. 15. Brainf*ck とは 番地 0 1 2 3 4 … データ 1 0 0 0 0 … + > + < -
  16. 16. Brainf*ck とは 番地 0 1 2 3 4 … データ 1 1 0 0 0 … + > + < -
  17. 17. Brainf*ck とは 番地 0 1 2 3 4 … データ 1 1 0 0 0 … + > + < -
  18. 18. Brainf*ck とは 番地 0 1 2 3 4 … データ 0 1 0 0 0 … + > + < -
  19. 19. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 0 0 0 0 … . [ > , ] 入力 出力 'A' 'B' '0'
  20. 20. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 0 0 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  21. 21. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 0 0 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  22. 22. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 0 0 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  23. 23. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 65 0 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  24. 24. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 65 0 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  25. 25. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 65 0 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  26. 26. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 65 66 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  27. 27. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 65 66 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  28. 28. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 65 66 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  29. 29. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 65 66 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  30. 30. Brainf*ck とは 番地 0 1 2 3 4 … データ 64 65 66 0 0 … . [ > , ] 入力 出力 'A' 'B' '0' '@'
  31. 31. Brainf*ck とは ● これだけの命令記号で ( 無限長の配列なら ) チューリング完全 – 他のプログラミング言語でできることなら ( 理論上 ) なんで もできる ● 「でも実際に実装するのはほぼ無理でしょ ? 」
  32. 32. Brainf*ck とは ● これだけの命令記号で ( 無限長の配列なら ) チューリング完全 – 他のプログラミング言語でできることなら ( 理論上 ) なんで もできる ● 「でも実際に実装するのはほぼ無理でしょ ? 」 – 実はある程度のパターンを知ればわりと実装できる !!!
  33. 33. Brainf*ck とは ● これだけの命令記号で ( 無限長の配列なら ) チューリング完全 – 他のプログラミング言語でできることなら ( 理論上 ) なんで もできる ● 「でも実際に実装するのはほぼ無理でしょ ? 」 – 実はある程度のパターンを知ればわりと実装できる !!! – 今回は実際に様々なプログラムを Brainf*ck で書いていき ます
  34. 34. 開発環境の入手
  35. 35. 開発環境の入手 ● ブラウザ上で実行できるインタプリタを用意しました – http://moon.kmc.gr.jp/~prime/brainf_ck/env/ – デバッグを ON にすると今どこを処理しているかやメモリの内 容が可視化される ● @ に到達すると一時停止 ( ブレークポイント ) – デバッグ OFF にすると高速に処理 ● マシンにもよるが数百万 step/s くらい ? – デバッグ ON かつ wait を 0ms にすると高速に処理してかつブ レークポイントが有効になる – めちゃくちゃステップ数のかかる処理をデバッグ OFF で実行 すると固まる
  36. 36. 開発環境の入手 ● 最適化のかかるインタプリタを C++ で用意しました – http://moon.kmc.gr.jp/~prime/brainf_ck/bfi.cpp – C++11 でコンパイルしてください ● gcc/clang ならコンパイルオプションに -std=c++11 ● C++ のコードに変換するコンパイラ (?) も用意しました – http://moon.kmc.gr.jp/~prime/brainf_ck/bfc.cpp – 一応無駄な処理をある程度省いたコードが生成される – こちらも C++11 必須
  37. 37. サンプルコードの入手 ● 今日使うサンプルコードをおいておきます – http://moon.kmc.gr.jp/~prime/brainf_ck/bftext/ – このページを常に開いておくことをおすすめします ● ASCII コード表もすぐに参照できるようにしておくのがよいで しょう – 「 ASCII コード表」とかで検索すると出てきます
  38. 38. ● ここからいよいよ実際にどうコーディングするかを解説します ● 今回は「なるべく書きやすいコーディング方法」を紹介します – その分コードが冗長になったり低速になったりします – 入力が正しいかをチェックしません – どうすればより短く , より高速に動作するコードが書けるか 研究してみてください ● 説明のために記号を導入します – {n} で n 番地の値を表す . 例えば {5} なら 5 番地の値 .
  39. 39. 入門編
  40. 40. 入門編 :for ループ ● for ループ – {0} の値の回数だけ *** という処理を行う – コード )[***-] – *** を行うたびに {0} の値を 1 減らす – ! 注意 !*** の中で {0} の値を変更しないこと ,*** が終 わった時点で 0 番地にいること ● 次から出てくるのは for ループのいろいろな使い方
  41. 41. 入門編 : 初期化 , 代入 ● 初期化 – {0} の値を 0 クリアする – コード )[-] – 0 になるまで 1 減らす , という操作を行う . ● 代入 – {0} に自分の好きな定数を代入する – コード )[-]+++++++ – 0 クリアして必要な数だけ + を重ねる
  42. 42. 入門編 : 値の移動 , 足し算 ● 値の移動 – {0} から {1} に値を移動する . – 最初 {1} は 0 だったとする . – コード )[>+<-] – {1} の値を 1 増やし ,{0} の値を 1 減らす , ということを {0} が 0 になるまで繰り返す ● 足し算 – {0} と {1} の和を {1} に入れる – コード )[>+<-] – 値の移動と同じコード
  43. 43. 入門編 : 引き算 , 値のコピー ● 引き算 – {1} から {0} を引いた値を {1} に入れる – コード )[>-<-] – {1} と {0} を 1 減らすことを {0} が 0 になるまで繰り返す ● 値のコピー ● Brainf*ck ではほとんどの操作が破壊的変更を加えるので , 頻繁に値のコピーが必要になる – {0} の値を {1} にコピー ( 一時変数として {2} を使う ) – コード )[>+>+<<-]>>[<<+>>-] – {0} の値を {1} と {2} に同時に移したあと ,{2} の値を {0} に移動する
  44. 44. 入門編 : 掛け算 ● 定数倍 – {0} の値の 5 倍を {1} に入れる – コード )[>+++++<-] ● 掛け算 – {0} と {1} の積を {2} に入れる ({3} を一時変数として使 う ) – コード )[>[>+>+<<-]>>[<<+>>-]<<<-] – 足し算と値のコピーの合わせ技 – {0} が 0 になるまで「 {1} の値を {2} に足すたびに {0} の 値を 1 減らす」を繰り返す
  45. 45. 入門編 : 演習 ● 数字二文字を入力にとってその和を出力する Brainf*ck コー ドを書きましょう ● とりあえず次の条件で作ってみましょう – 数字二文字 (ASCII コードで 48~57 が '0' から '9' に対 応 ) 以外の入力は与えられない – 計算結果は繰り上がりしない
  46. 46. 入門編 : 演習 ● コード例 – ,>,>++++++[<-------->-]<<[>+<-]>. – 幸いにも ASCII コードは小さい順に並んでいるの で '0'=48 を引けば数値になる
  47. 47. 入門編 : スタック ● スタックと Brainf*ck の命令体系は親和性が高い – push が > に ,pop が < に対応している – スタックに 3,2,3 を積み , その積を計算する – コード )+++>++>+++> << >[<[>>+>+<<<-]>>>[<<<+>>>-]<<-]<[-]>>[<<+>>-]<< > << >[<[>>+>+<<<-]>>>[<<<+>>>-]<<-]<[-]>>[<<+>>-]<< >
  48. 48. 入門編 : 再帰 ● 再帰 : 関数からその関数自身を呼ぶこと – 再帰を使うと処理が簡潔に書けるケースがたくさん知られ ている
  49. 49. 入門編 : 再帰 ● 再帰 : 関数からその関数自身を呼ぶこと – 再帰を使うと処理が簡潔に書けるケースがたくさん知られ ている ● 実は再帰はスタックを用いて書ける – 再帰関数の引数をスタックに積むことで実現する
  50. 50. 入門編 : 再帰 ● 再帰 : 関数からその関数自身を呼ぶこと – 再帰を使うと処理が簡潔に書けるケースがたくさん知られ ている ● 実は再帰はスタックを用いて書ける – 再帰関数の引数をスタックに積むことで実現する →Brainf*ck ではスタックが使える !!!
  51. 51. 入門編 : 再帰 ● 再帰 : 関数からその関数自身を呼ぶこと – 再帰を使うと処理が簡潔に書けるケースがたくさん知られ ている ● 実は再帰はスタックを用いて書ける – 再帰関数の引数をスタックに積むことで実現する →Brainf*ck ではスタックが使える !!! →Brainf*ck では再帰が書ける !!!!!
  52. 52. 入門編 : 再帰 ● 再帰 : 関数からその関数自身を呼ぶこと – 再帰を使うと処理が簡潔に書けるケースがたくさん知られ ている ● 実は再帰はスタックを用いて書ける – 再帰関数の引数をスタックに積むことで実現する →Brainf*ck ではスタックが使える !!! →Brainf*ck では再帰が書ける !!!!! ● 再帰を用いた実践的なコードを書いてみます
  53. 53. ハノイの塔 ● リュカという数学者が考案したと言われるパズルゲーム ● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左 端の棒に大きいものが下になるように置かれている ● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させる – 一度に動かせるのは棒の一番上の円盤どれか一枚のみ – 小さい円盤の上に 大きい円盤を載せる ことはできない
  54. 54. ハノイの塔 ● リュカという数学者が考案したと言われるパズルゲーム ● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左 端の棒に大きいものが下になるように置かれている ● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させる – 一度に動かせるのは棒の一番上の円盤どれか一枚のみ – 小さい円盤の上に 大きい円盤を載せる ことはできない
  55. 55. ハノイの塔 ● リュカという数学者が考案したと言われるパズルゲーム ● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左 端の棒に大きいものが下になるように置かれている ● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させる – 一度に動かせるのは棒の一番上の円盤どれか一枚のみ – 小さい円盤の上に 大きい円盤を載せる ことはできない
  56. 56. ハノイの塔 ● リュカという数学者が考案したと言われるパズルゲーム ● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左 端の棒に大きいものが下になるように置かれている ● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させる – 一度に動かせるのは棒の一番上の円盤どれか一枚のみ – 小さい円盤の上に 大きい円盤を載せる ことはできない
  57. 57. ハノイの塔 ● リュカという数学者が考案したと言われるパズルゲーム ● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左 端の棒に大きいものが下になるように置かれている ● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させる – 一度に動かせるのは棒の一番上の円盤どれか一枚のみ – 小さい円盤の上に 大きい円盤を載せる ことはできない
  58. 58. ハノイの塔 ● リュカという数学者が考案したと言われるパズルゲーム ● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左 端の棒に大きいものが下になるように置かれている ● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させる – 一度に動かせるのは棒の一番上の円盤どれか一枚のみ – 小さい円盤の上に 大きい円盤を載せる ことはできない
  59. 59. ハノイの塔 ● リュカという数学者が考案したと言われるパズルゲーム ● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左 端の棒に大きいものが下になるように置かれている ● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させる – 一度に動かせるのは棒の一番上の円盤どれか一枚のみ – 小さい円盤の上に 大きい円盤を載せる ことはできない
  60. 60. ハノイの塔 ● リュカという数学者が考案したと言われるパズルゲーム ● 三本の棒と大きさの異なる n 枚の円盤があり , 最初円盤は左 端の棒に大きいものが下になるように置かれている ● 次の規則を満たしつつ , 全ての円盤を右端の棒に移動させる – 一度に動かせるのは棒の一番上の円盤どれか一枚のみ – 小さい円盤の上に 大きい円盤を載せる ことはできない
  61. 61. ハノイの塔 ● ハノイの塔は再帰的な手続きによって最短で解けることが知 られている ● 何らかの方法で左端の上から n-1 枚の円盤を真ん中の棒 に移動させる ● 左端にある一番大きな円盤を右端の棒に移動させる ● 何らかの方法で真ん中の棒の n-1 枚の円盤を右端の棒に 移動させる ● 「何らかの方法」のところにこの手続き自身を使える ( 再帰的 な手続き ) ● 実はこの方法が最短 ● 円盤が n 枚なら最短手数は 2^n-1
  62. 62. Brainf*ck でハノイの塔 ● ハノイの塔を解くプログラムを Brainf*ck で作っていく ● 具体的な動かし方を ' 円盤の名前 ' ' 動かす前の棒の番号 ' ' 動かす先の棒の番号 ' の形で出力する ● 円盤には小さい方から A,B,C,… と名前を付ける ( 最大 26 枚 ) ● 棒には左から 1,2,3 と番号を付ける ● 円盤 2 枚の場合の出力例 A 1 2 B 1 3 A 2 1
  63. 63. Brainf*ck でハノイの塔 ● プログラムの動作を擬似コードで書く Hanoi(n,a,b)//n 枚の円盤を a から b に動かす Hanoi(n-1,a,c) Move(n,a,b) Hanoi(n-1,c,b) end ● Move は n 番目に小さい円盤を a から b に動かすという出力を する .Move(5,1,2) なら E 1 2 と出力する ● c は {1,2,3} のうち a でも b でもない数
  64. 64. Brainf*ck でハノイの塔 ● c は 6-a-b で求められる ( 引き算だから簡単 !) ● Hanoi の中で Move という別の関数を呼ぶ処理は書きにくい – よく見ると Hanoi と Move は引数の形が同じ – 引数を一つ増やした Hanoi'(n,s,a,b) を考えて ,s=1 なら Hanoi,s=0 なら Move の処理をするという条件分岐の形に する ● スタックに積むのは (n,s,a,b) という値の四つ組 ● スタックから 4 個ずつ値を積んだり取り出したりすることで再 帰的手続きを実現する ● s=0 なら , 〜〜という処理は if 文がないので ,s=1 である限 り Hanoi を繰り返し , そのループを抜けたあとに Move をす る , という形で書く
  65. 65. Brainf*ck でハノイの塔 ①最初にスタックに (n,s,a,b)=(n,1,1,3) を積む ②スタックの一番上の値を読み、 s=0 なら 6 に飛ぶ ③スタックから取り出した値が (n,1,a,b) だったとすると それを消してスタックに (n-1,1,a,6-a-b),(n,0,a,b), (n-1,1,6-a-b,b) を積む ④スタックの一番上の値を読み、 (1,*,*,*) でないなら 3 に 戻る ⑤スタックの一番上の値を読み、 s を 1 から 0 にする ⑥スタックから取り出した値を出力する。たとえば (3,0,1,3) だったら C 1 3 を出力する ⑦スタックの一番上の値が (0,*,*,*) でないなら 2 に戻る
  66. 66. Brainf*ck でハノイの塔 ● 実際のコード >>>>++++>+>+>+++<<<[>[<-[[>>>>+>>>>+>>>>+<<<<<<<<<<<<- ]>[>>>>+>>>>+>>>>+<<<<<<<<<<<<-]>[>>>>+>>>>+>>>>+<<<<< <<<<<<<-]>[>>>>+>>>>+>>>>+<<<<<<<<<<<<-]<++++++>>+>->> >>>>>[<<<<<<<<<<<<+>>>>>>>>>>>>-]>[<<<<<<<<<<<<+>>>>>> >>>>>>-]>[<<<<<<<<<<<<->>>>>>>>>>>>-]>[<<<<<<<<<<<<+<- >>>>>>>>>>>>>-]<<<<<[>>+>+<<<-]>[>+<-]++++++>[<->-]>[< <<+>>>-]<<<<<-]+>-]++++++++[>++++++>++++++<<<++++++++> -]>>>>++++[<++++++++>-]<<<<<.[-]>>>>.<<.[-]>>.[-]<.[-] ++++++++++.[-]<<<<<<<] (454bytes)
  67. 67. Brainf*ck でハノイの塔 ● 見やすく整形すると >>>>+>+++++[<+++++>-]+>+>+++<<< [>[ <-[ [>>>>+>>>>+>>>>+<<<<<<<<<<<<-] >[>>>>+>>>>+>>>>+<<<<<<<<<<<<-] >[>>>>+>>>>+>>>>+<<<<<<<<<<<<-] >[>>>>+>>>>+>>>>+<<<<<<<<<<<<-] <++++++>>+>->>>>>>> [<<<<<<<<<<<<+>>>>>>>>>>>>-] >[<<<<<<<<<<<<+>>>>>>>>>>>>-] >[<<<<<<<<<<<<->>>>>>>>>>>>-] >[<<<<<<<<<<<<+<->>>>>>>>>>>>>-] <<<<<[>>+>+<<<-] >[>+<-]++++++>[<->-]>[<<<+>>>-] <<<<<- ]+>- ]++++++++[>++++++>++++++<<<++++++++>-]>>>>++++[<+++++++ +>-]<<<<<.[-]>>>>.<<.[-]>>.[-]<.[-]++++++++++. [-]<<<<<<<] Hanoi(n,a,b) Move(n,a,b)
  68. 68. 初級編
  69. 69. 初級編 :if イディオム ● Brainf*ck には while 文に相当する [,] はあるが ,if 文に 相当する構文はない ● while 文のループを 1 回で終えれば if 文と同じ動作になる – {0} が 0 でなければ *** の内容を実行 – コード )[***[-]] – ! 注意 ! *** の処理は最後に 0 番地に戻ること ● else 文も少しの工夫で実現可能 – {0} が 0 でなければ *1*,0 なら *0* の内容を実行 – コード )>+<[*1*>-<[-]]>[*0*-] – ! 注意 ! *1* は 0 番地に ,*0* は 1 番地に戻ること – {1} をフラグとして用いて else 文を実現している
  70. 70. 初級編 :if イディオム ● 二つの値が等しい・等しくないで分岐する – {0}={1} なら *1* を , そうでないなら *0* を実行する – コード )[>-<-]>>+<[*1*>-<[-]]>[*0*-] – {1}-{0} を計算して 0 かどうかで場合分けしている ● 値をコピーしておけば if を連鎖して switch のようにすること も可能
  71. 71. 初級編 : 大小比較 ● 大小比較 – {0}<{1} なら *0* を , そうでないなら *1* を実行 ( 一時変 数として {2},{3} を使用 ) – コード ) [>>>+<<[-<->[>+<-]>>-<<]>[<+>-]>[-<<<[-]>>>]<<<] +>[*0*<->[-]]<[*1*[-]] – ! 注意 ! *0* は 1 番地に ,*1* は 0 番地に戻ること – 「 {0},{1} が両方正なら 1 ずつ減らし , 減らす前の {1} が 0 だったら {0} も 0 にする」という操作を {0} が正の間行 い ,{1} が 0 かそうでないかで場合分けしている
  72. 72. 初級編 : 除算 ● 除算 – {0}÷{1} の商を {6} に , 余りを {7} に入れる ({2} 〜 {5} を一時変数として使う ) – コード ) [[>>+>+<<<-]>>>[<<<+>>>-]<<[>>+>+<<<-]>>>[<<<+>> >-]<<[>>>+<<[-<->[>+<-]>>-<<]>[<+>-]>[-<<<[-]>>> ]<<<]+>[[-]<<<[>>>>>>>+<<<<<<<-]>>->]<[-<[>+<<-> -]>[<+>-]>>>>+<<<<]<<] – {0}≧{1} である間 , 「 {0} から {1} を引き ,{6} に 1 加え る」ということを繰り返し ,{0}<{1} になったら {0} を {7} に入れる
  73. 73. 初級編 : 配列 ● ランダムアクセス出来る配列を実現したい – 例 ) 配列の {0} 番目の値を参照する ● 次のようにデータを配置することで可能 ● 2 バイトごとに一つの値を格納する (1 セクションと呼ぶことにする ) – 1 バイト目に値 – 2 バイト目は計算領域 ( 最初は 0 で埋めておく ) ● 配列へのアクセス – コード )[[>>+<<-]>>-] – セクションをひとつずつ移動しながら , 値を 2 つ横に移動して 1 減ら す , ということを値が 0 になるまで繰り返すと , 終了した時にはポイ ンタは a[{0}] の直前を指している 番地 0 1 2 3 4 5 6 7 8 … 値 {0} 0 0 0 0 …a0 a1 a2 a3
  74. 74. 初級編 : 配列 ● 配列を走査したい ● 配列の端を求めたい ● 1 セクションを 3 バイト区切りにする – 1 バイト目に値 – 2 バイト目に 1: 直前に値があることを示す – 3 バイト目は計算領域 ● 3n 番地から配列の終端まで飛ぶ – コード )[>>>]<<<< – セクションの 2 バイト目が番兵の役割を果たしている 番地 0 1 2 3 4 5 6 7 … m m+1 m+2 m+3 m+4 値 0 0 1 0 1 0 … 1 0 0 0a0 a1 an−1
  75. 75. 初級編 : 配列 ● 同様にして配列の先頭に飛ぶことも出来る ● セクションをひとつずつ移動し , そのセクションの 2 バイト目 が 1 の間 ~ する , というコードを書くことで配列を走査出来る ● この方法でデータを格納すると (256 バイト以上はランダムア クセスするのは難しいが ) いくらでも長い配列を用意できる 番地 0 1 2 3 4 5 6 7 … m m+1 m+2 m+3 m+4 値 0 0 1 0 1 0 … 1 0 0 0a0 a1 an−1
  76. 76. 初級編 : 配列 ● ポインタを使いたい ( 今居る場所を記憶して後で戻りたい ) – ひとつの配列にひとつのポインタであれば , ポインタの指 している区切りの 2 バイト目を 0 にすることで実現できる – コード )[>>>] – 3 番地から始めるとポインタの指す先 , ポインタの指す先 の次のセクションの 2 バイト目から始めると配列の末尾に 飛べる ● 256 バイト以上あっても使える 番地 0 1 2 3 4 5 6 7 … m m+1 m+2 m+3 m+4 値 0 0 1 0 1 0 … 1 0 0 0a0 a1 an−1
  77. 77. 初級編 : 配列 ● この場合のポインタというのは , 参照している場所を保存する ためのデータ構造といえる – アドレスを格納する変数を用意しようと思うと ,256 要素以 上の配列に対しては多倍長整数が扱える必要がある ● 多倍長整数を扱うのにも配列が必要になるため , 処理 が大変なことになる ● 今後この形式の配列をポインタフラグ付き配列と呼ぶ
  78. 78. 初級編 : 配列 ● 長さ {0} のポインタフラグ付き配列を作る ( 配列の最初の要素 が来るのは 3 番地 ) – コード )[>>>>[>>>]+[<<<]<-] ● ポインタフラグ付き配列のコピー – 最初配列の先頭にポインタがあるものとする – コード ) >[-<[>>+>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]<-]>>[<<+ >>-]>>[>>>]>>>[>>>]+[<<<]<<<[<<<]+>>>] – 1 セクションごとに「まず値をコピーし , つぎにポインタフラグ をコピーする」ということをする
  79. 79. Brainf*ck で Brainf*ck インタプリタ ● 初級編で取り上げた条件分岐や配列を使ったプログラムとし て ,Brainf*ck で Brainf*ck のインタプリタを書いてみます ● 仕様 – Brainf*ck のソースコードを標準入力で受け取る ● '!' が現れる前までをソースコード , その後を標準入 力として扱う ● 実装 – ソースコードを格納するポインタフラグ付き配列とデータを 格納するポインタフラグ付き配列を持つ – ソースコードを読み込み , それに対応する操作をデータに 対して施す
  80. 80. Brainf*ck で Brainf*ck インタプリタ ● ソースコードとデータの配列は次のように配置する ● ck: ソースコードの k 文字目 ● dk: 配列の k 番目の値 ● pk,qk: プログラムポインタフラグ , データポインタフラグ ● 今ソースコードのどこを読んでいるかを指すポインタフラグと , データ を指すポインタフラグを持つ – それぞれプログラムポインタフラグ , データポインタフラグと呼ぶ ● プログラムポインタの指すところからデータポインタの指すところまで 飛ぶのは簡単 – コード )>>>[>>>]>>>[>>>] 0 0 0 0 c1 p1 0 c2 p2 0 … … cn pn 0 0 0 0 d0 q0 0 …
  81. 81. Brainf*ck で Brainf*ck インタプリタ ①標準入力から ! が現れるまで読み込み , ソースコードを格納 する配列に格納する . プログラムポインタフラグは p1 を 0, それ 以外を 1 にする ②プログラムポインタの指す文字を読み ,+ なら③ ,, なら ④ ,- なら⑤ ,. なら⑥ ,< なら⑦ ,> なら⑧ ,[ なら⑨〜⑪ ,] な ら⑫〜⑭を実行し , それが終わったらそれぞれ⑮に行く ③(+ の処理 ) データポインタまで飛び , 値を 1 増やし , プログラ ムポインタまで戻る ④(, の処理 ) データポインタまで飛び , 標準入力からひとつ読 んでポインタの指す値に代入し , プログラムポインタまで戻る ⑤(- の処理 ) データポインタまで飛び , 値を 1 減らし , プログラ ムポインタまで戻る ● プログラムの流れ
  82. 82. Brainf*ck で Brainf*ck インタプリタ ⑥(. の処理 ) データポインタまで飛び , 値を標準出力に出力 し , プログラムポインタまで戻る ⑦(< の処理 ) データポインタまで飛び , データポインタをひとつ 戻し , プログラムポインタに戻る ⑧(> の処理 ) データポインタまで飛び , データポインタをひとつ 進め , プログラムポインタに戻る ⑨([ の処理 ) データポインタまで飛び , 値が 0 でなければ⑪に 飛ぶ ⑩プログラムポインタに飛び , ソースコードの配列をプログラム ポインタを前進させながら進んでいき ,[ と ] の数を数え , 同じに なったところでとめ , データポインタまで戻る ⑪プログラムポインタまで戻る
  83. 83. Brainf*ck で Brainf*ck インタプリタ ⑫(] の処理 ) データポインタまで飛び , 値が 0 ならば⑭に飛ぶ ⑬プログラムポインタに飛び , ソースコードの配列をプログラム ポインタを後退させながら戻っていき ,[ と ] の数を数え , 同じに なったところで止め , データポインタまで戻る ⑭プログラムポインタまで戻る ⑮プログラムポインタをひとつ進め , プログラムポインタの指す 文字が 0 でなければ②に戻る あとはこれをコードに落としこんでいく
  84. 84. Brainf*ck で Brainf*ck インタプリタ ● 実際のコード >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] (1681bytes)
  85. 85. Brainf*ck で Brainf*ck インタプリタ ● 分かるかボケ – はい
  86. 86. Brainf*ck で Brainf*ck インタプリタ ● 分かるかボケ – はい – 全体を眺めていても何がなんだかわからないので部分ご とに見て行きます
  87. 87. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) プログラムの読み込み
  88. 88. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) もし + ならば〜
  89. 89. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) もし , ならば〜
  90. 90. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) もし - ならば〜
  91. 91. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) もし . ならば〜
  92. 92. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) もし < ならば〜
  93. 93. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) もし > ならば〜
  94. 94. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) もし [ ならば〜
  95. 95. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) もし ] ならば〜
  96. 96. >>>>,--->+++++[<------>-]<[+++>+++++[<++++++>-]+>>,--->+++++[<------>-]<]<<[<<<] >>>-<[[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<------->>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<- ------>>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<,<<[<<<]<<<[<<<] >-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>> >-]<<<[>>[>>>]>>>[>>>]<-<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++[<<--- ------>>-]+<<-[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]<.<<[<<<]<<<[<<<]> -]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++[<<---------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>> >>-]<<<[>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]++++++ ++[<<-------->>-]+<<++[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[>>[>>>]>>>[>>>]+>>>[-]<<< [<<<]<<<[<<<]>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]>+<<[[<+>-]>>-<<]<[>+<-]>>>[-<<<<[<<<] <<<[<<<]>+[<+>>>-<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<[[-]>>- <<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------- ----->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<->>>-]<<<[>>>+<<<-]>>>]>>[>>>] >>>[>>>]>]<<<<[<<<]<<<[<<<]>]<<[>>+>>>+<<<<<-]>>[<<+>>-]+++++++[<<-------------> >-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[->>[>>>]>>>[>>>]<[>>+>>>+<<<<<-]>>>>>[< <<<<+>>>>>-]<<<[[-]<<<<[<<<]<<<[<<<]<<<<<-[>>->>>+<<<<[>>+>>>+<<<<<-]>>[<<+>>-]+ ++++++[<<------------->>-]+<<[[-]>>-<<]>>>>>[<<<<<+>>>>>-]<<<[<<<+>>>-]<<[>>+>>> +<<<<<-]>>[<<+>>-]+++++++[<<------------->>-]+<<--[[-]>>-<<]>>>>>[<<<<<+>>>>>-]< <<[<<<->>>-]<<<[<<<->>>+]<<<]>>>>>>>>[>>>]>>>[>>>]>]<<<<[<<<]<<<[<<<]>]<+>>>[-]< ] Brainf*ck で Brainf*ck インタプリタ ● 実際のコード (1681bytes) プログラムカウンタを進める
  97. 97. Brainf*ck で Brainf*ck インタプリタ ● 部分部分に分解していけばこれまでにやったことの組み合わ せでできる ● このインタプリタはめちゃくちゃ遅い – 比較するのに何回もコピーをとっている – データとソースコードを行ったり来たりするのにも時間がか かる – 実際に計測してみるとこのインタプリタを噛まさない場合に 比べて数万倍は遅い – 最悪で ( 数百くらいの定数 )×( ソースコードの長さ ) 倍遅 くなる – 色々と高速化出来る点はあるものの , 数百くらいある定数 が小さくなるだけでオーダーレベルでの改善はほぼ不可能
  98. 98. 中級編
  99. 99. 中級編 ● ここから難易度がインフレ !!!!! ● いちいち細かい実装を見ていると終わらない ● おおまかにどうやって実装するか , どのくらいのコード量 , 計 算量 , メモリ消費になるかに絞って見ていく
  100. 100. 中級編 : 多倍長整数 ● さすがに数値が 255 までしか扱えないのは色々と不便 – 大きな整数 ( できればメモリの許す限り大きな数 ) を扱いたい ● 今回は比較的実装の楽な二つの実装を紹介 – 実装量はそこそこでそこそこの計算量 – 実装量はとても少ないが計算量はかなり大きい – 目的に応じて使い分ける ● 元のデータを壊しても良いかどうかによってコード量がかなり変 わってくることがある – その場合は両方載せる ( 何も書いていないほうが破壊版 ) – 破壊版も使う数値の組のコピーを取れば非破壊版に直せる
  101. 101. 中級編 : 多倍長整数 ● 実装量はそこそこでそこそこの計算量になる実装 ● 値を 2 進数のポインタ付き配列で保存し ,3 バイト区切り一つ で 1 ビット格納する , 負の数は最上位 bit が 1 になる – メモリ消費量は桁数に比例 ● 以後のサンプルコードは演算する 2 数の bit 数が等しいもの と仮定 ● 計算量は足し算・引き算 O(log^2(n)), 掛け算 O(log^3(n))
  102. 102. 中級編 : 多倍長整数 ● 足し算 – 2 数の配列は 0,0,0 でつないであり , ポインタは 2 数の直 後を指しているものとする , オーバーフローはないと仮定 – コード ) <<[-<[<<[<<<]<<<[<<<]<+>>>>[>>>]>>>[>>>]<-]<<[< <<]<<<[<<<]<<<[-]>>>+[>>>]>>>[>>>]+<<<]<<<[-<[< +>>+<-]+[>>>>>+<<<<[-<->[>+<-]>>>>-<<<<]>[<+>-] >>>[-<<<<<[-]>>>>>]<<<<<]>[[-]<<--<<+>>>>]<<[>+ <-]>>+<<<] – 各桁ごとに足してから , 繰り上がりの計算をする ● その桁が 2 以上なら 2 を引き次の桁に 1 を足す , とい ことを下位 bit から順に行う – 繰り上がりの計算は事あるごとに出てくる
  103. 103. 中級編 : 多倍長整数 ● 引き算 – コード ) <<[<<+>[<->-]<[>+<-]<]>>>[>>>]<<<[-<[<<[<<<]<<<[ <<<]<+>>>>[>>>]>>>[>>>]<-]<<[<<<]<<<[<<<]<<<[-]> >>+[>>>]>>>[>>>]+<<<]<<<<+>[-<[<+>>+<-]+[>>>>>+< <<<[-<->[>+<-]>>>>-<<<<]>[<+>-]>>>[-<<<<<[-]>>>> >]<<<<<]>[[-]<<--<<+>>>>]<<[>+<-]>>+<<<]<[-] – 引く数の各ビットを反転し ,2 数を桁ごとに足し ,1 足して , 繰り上がりの計算をし , 最後に桁溢れの 1 を削る – ビット反転して 1 を足すと正負が逆転する – A-B を A+(-B) という形で計算している
  104. 104. 中級編 : 多倍長整数 ● 掛け算(非破壊版 ) – コード ) [->>>[>>>]>>>[>>>]>>>[>>>]+>>>+[<<<]<<<[<<<]<<<[<<<]+>>>]<<<[<<<]>>><[>>>>[>>>]> >>[>>>]>>>[>>>]>>>>>+<<<<<<<<[<<<]<<<[<<<]<<<[<<<]>>>[>+<<[>>-<<-]>>[<<+>>-]>>]< <<<+>[-<[<+>>+<-]+[>>>>>+<<<<[-<->[>+<-]>>>>-<<<<]>[<+>-]>>>[-<<<<<[-]>>>>>]<<<< <]>[[-]<<--<<+>>>>]<<[>+<-]>>+<<<]>>]>[>>>]>>><[>>>>[>>>]>>>[>>>]>>>>>>>+<<[>>-< <-]>>[<<+>>-]<<<<<<<<<<[<<<]<<<[<<<]>>>[>+<<[>>-<<-]>>[<<+>>-]>>]<<<<+>[-<[<+>>+ <-]+[>>>>>+<<<<[-<->[>+<-]>>>>-<<<<]>[<+>-]>>>[-<<<<<[-]>>>>>]<<<<<]>[[-]<<--<<+ >>>>]<<[>+<-]>>+<<<]>>]<<<<<[<<<]>>>[->>>[>>>]>>>[>>>]>>>-<<<<<<[<<<]<<<[<<<]<<< [->>>[>>>]>>>[>>>]>>>[>>>]>>>[>>>]+>>>-<<<[<<<]<<<[<<<]<<<[<<<]<<<[<<<]+<<<]>>>[ >>>]>>>[>>>]>>>[->>>[>>>]>>>[>>>]+>>>[-]<<<[<<<]<<<[<<<]+>>>]<<<[<<<]<<<[<<<]<[> >>>[>>>]>>>[>>>]<<<[-<[>>>>[>>>]>>>[>>>]<+<<[<<<]<<<[<<<]<[>>+<<-]]>>[<<+>>-]>>[ >>>]>>>[>>>]+<<<[-]<<<[<<<]<<<[<<<]+<<<]>>>[>>>]>>>[>>>]>>>[>>>]<<<[-<[<+>>+<-]+ [>>>>>+<<<<[-<->[>+<-]>>>>-<<<<]>[<+>-]>>>[-<<<<<[-]>>>>>]<<<<<]>[[-]<<--<<+>>>> ]<<[>+<-]>>+<<<]<<<[<<<]<<<[<<<]<<<[<<<]<[>>+<<-]]>>[<<+>>-]>>[>>>]>>>[>>>]>>>[> >>]+[<<<]<<<[<<<]<<<[<<<]+>>>]>>>[>>>]>>>[>>>]<<<[-<[<+>>+<-]+[>>>>>+<<<<[-<->[> +<-]>>>>-<<<<]>[<+>-]>>>[-<<<<<[-]>>>>>]<<<<<]>[[-]<<--<<+>>>>]<<[>+<-]>>+<<<]>> >[>>>]>>>>>[-<<<<<<<<[>+<<[>>-<<-]>>[<<+>>-]<<<<]>>>[>>>]<<<<+>[-<[<+>>+<-]+[>>> >>+<<<<[-<->[>+<-]>>>>-<<<<]>[<+>-]>>>[-<<<<<[-]>>>>>]<<<<<]>[[-]<<--<<+>>>>]<<[ >+<-]>>+<<<]>>>[>>>]>>>>>]<<<<<<<<-<<<[<<<]<<<[->>>[>>>]>>>[>>>]+<<<-<<<[<<<]<<< [<<<]+<<<]>>>[>>>]>>>[>>>]+>>>-<<<[<<<]>>>>>>[[>>>]<<<-<[-]>>>>>>>[<[<<<+>>>-]>> >>]<<<-<<<[<<<]+<<<<<<[<<<]>>>>>>]>>>[<[<<<+>>>-]>>>>]<<<-<<<[<<<]+<<<<<<[<<<]>> >
  105. 105. 中級編 : 多倍長整数 ● 掛け算 – まず ,2 つの数の符号を調べ , 積が正負どちらになるか保 存して ,2 つの数を正の数に直す – 長さ 2n の配列を用意 – いわゆる筆算をする ● – n 回足し算をしているが ,1 回足し算をするごとに繰り上が りの計算をしている – 符号が負だったら負の数に直し , 符号を除く上位 n 桁を 落とす – コードが長くなるのは複数の配列を行ったり来たりしてい るから A×B= A×b0×20 + A×b1×21 +⋯
  106. 106. 中級編 : 多倍長整数 ● ( 実質的な ) 実装量は少ないが計算量はかなり大きい実装 ● 2 進数でもめんどくさいのは繰り上がりがあるから – 繰り上がりの問題を何とかしたい
  107. 107. 中級編 : 多倍長整数 ● ( 実質的な ) 実装量は少ないが計算量はかなり大きい実装 ● 2 進数でもめんどくさいのは繰り上がりがあるから – 繰り上がりの問題を何とかしたい ● !!!1 進数多倍長 !!! ● 1 進数なら繰り上がりは常に発生するので煩わしい分岐をす る必要がなくなる ! ● 非破壊版の計算量は足し算・引き算が O(n^2), 掛け算が O(n^3)
  108. 108. 中級編 : 多倍長整数 ● まずは自然数 (0 以上の整数 ) を表現する方法を考える – 連続する 1 の個数で表現する – 10 億を表すのに約 1GB のメモリを消費する – それでも無限のメモリがあればどんなに大きな値も表せる ● 足し算 – コード )[>]+[>]<- – ただ単に連結するだけ ● 前にひとつずらす – 1 進数は計算により長さが変化しうるのでそれに合わせて周り の自然数を動かす必要がある – コード )[>]<[[<]+[>]<-] 0 1 1 1 … 1 1 1 0
  109. 109. 中級編 : 多倍長整数 ● コピー – [->[>]>[>]+[<]<[<]+>] – 1 進数多倍長の計算はほとんどコピーの組み合わせ ● 足し算 ( 非破壊版 ) – コード )[->[>]>[>]>[>]+[<]<[<]<[<]+>]>[->[>]>[>]+ [<]<[<]+>] – 2 数を同じ場所にコピー ● 掛け算 ( 非破壊版 ) – コード )[->[>]>[->[>]>[>]+[<]<[<]+>]<[<]<[<]+>] – かけられる数の要素数分だけ「かける数をコピー」という操 作をする
  110. 110. ● 引き算 ( 片方が 0 になるまで ) – コード ) [[>]>[[>]>+<<[<]]<[<]]>[>]>[>]>[-<<-<[<]<[<]>->[ [>]>[[>]>+<<[<]]<[<]]>[>]>[>]>] ● 割り算 ( 非破壊版 ) – コード ) [->[>]>[>]>[>]+[<]<[<]<[<]+>]>[>]>[>]+[<]>[<<[<] >[->[>]>[>]<[->>[>]<[[<]+[>]<-]<[<]<[<]]<[<]+>]> [[>]>[>]+[<]<[<]>[<+>-]]<[>+<-]>] – 割る数で割られる数を引ける回数を求めている
  111. 111. 中級編 : 多倍長整数 ● 負の数も表現したい ● 符号を格納する領域を作っても良いが , 符号によって場合分 けが必要になり , 大変 ● 2 つの自然数を組にして , その差として表現する – (x,y) という組で x-y という整数を表す ● (0,2),(3,5),(100000,100002) はすべて -2 を表す ● (x1,y1)+(x2,y2)=(x1+x2,y1+y2) ● (x1,y1)-(x2,y2)=(x1+y2,x2+y1) ● (x1,y1)*(x2,y2)=(x1*x2+y1*y2,x1*y2+x2*y1) ● 適宜片方が 0 になるまで引き算して数字が爆発的に増えるの を防ぐ

×