Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

実用Brainf*ckプログラミング入門編

7.127 Aufrufe

Veröffentlicht am

実用Brainf*ckプログラミング入門編 prime@KMC

  • Als Erste(r) kommentieren

実用Brainf*ckプログラミング入門編

  1. 1. 実用Brainf*ckプログラミング 入門編 KMC1回生 prime(twitter:@_primenumber)
  2. 2. はじめに:Brainf*ckとは ● 命令記号は+-><[].,の8種類だけ! ● 1993年にできた、できるだけコンパイラが小さくなるよう なプログラミング言語 ● 難解になるべくして生まれたわけではない ● 実際、命令記号は読みやすいように選ばれている ● 処理系が作りやすいので、しばしばプログラミングの練習 問題としてBrainf*ckインタプリタの作成をさせたり、派 生言語が作られたりする
  3. 3. 言語仕様 ● はじめに0で初期化された十分な長さの配列が与えられる ● C言語で言うポインタを操作して動作。最初は0番地 ● +/- ポインタの指す値を1増やす/減らす ● >/< ポインタをインクリメント/デクリメントする ● [ ポインタの指す値が非0なら対応する]の直後にジャンプ ● ] ポインタの指す値が0なら対応する[の直後にジャンプ ● . ポインタの指す値を文字として出力する ● , 入力から1バイト読み、ポインタの指す値に代入する ● これら8種類の文字以外については動作は未定義だが、 多くの処理系では無視する
  4. 4. Brainf*ckでできること ● これだけの命令記号で(無限長の配列なら)チューリング 完全 – 他のプログラミング言語でできることなら(理論上)な んでもできる ● でも実際に実装するのはほぼ無理でしょ?
  5. 5. Brainf*ckでできること ● これだけの命令記号で(無限長の配列なら)チューリング 完全 – 他のプログラミング言語でできることなら(理論上)な んでもできる ● でも実際に実装するのはほぼ無理でしょ? →実はある程度のパターンを覚えれば、 わりと実装できる!!!
  6. 6. 今日やること ● 入門編なので少しだけ ● 値のクリア・代入、足し算/引き算、値のコピー、掛け 算、スタック ● 最後にこれらを使って実際に動くプログラムを作ります ● 説明の中で省略記号を使います – ポインタが最初に指している場所を[0]と書き、[n] でそこからn番地進んだ場所を表す
  7. 7. 値のクリア・代入 ● 値をクリアしたり代入するとき ● 値のクリア:[0]の値を0にする ● [-] ● 動作:[0]の値が0になるまで1減らす ● 値の代入:[0]の値を5にする ● [-]+++++ ● 動作:[0]の値をクリアして5を足す
  8. 8. 足し算・引き算 ● かなり使う ● 足し算:[0]の値を[1]に足す([0]の値は消える) [>+<-] ● 動作:「[1]の値を1増やし、[0]の値を1減らす」を[0]が 0になるまで繰り返す ● [1]の値が0なら値の移動になる ● 引き算:[0]の値を[1]から引く [>-<-]
  9. 9. 値のコピー ● 足し算や引き算をするとどちらかの値が消えてしまう ● Brainf*ckではほとんど非破壊的な動作はできない ● →値のコピーが必要 ● 値のコピー:[0]の値を[1]にコピー([2]を一時変数とし て使う) [>+>+<<-]>>[<<+>>-] ● [0]の値を[1]と[2]に書き込む([0]の値は消える) ● [2]の値を[0]に書き込む([2]の値は消える)
  10. 10. 掛け算 ● 足し算と値のコピーを繰り返す ● 掛け算:[0]と[1]の積を[2]に書き込む([3]を使う) [<[>>+>+<<<-]>>>[<<<+>>>-]<<-] ● [0]の値を[2]と[3]に足し、[3]の値を[0]に書き込む ● [1]の値を1減らす ● これを[1]の値が0になるまで繰り返す ● 定数の掛け算は簡単にできる ● 定数の掛け算:[0]の5倍を[1]に入れる [>+++++<-]
  11. 11. スタック ● そもそもBrainf*ckはデータメモリがそのままスタック に使える ● スタックに積む (値を書き込む)> ● スタックから値を取り出す <(値を使う) ● サンプル: まずスタックに3つ値を積む スタックから2つ取り出し積を計算して値を積む
  12. 12. 再帰 ● 関数の中でその関数自身を呼び出すこと ● うまく使うとプログラムが簡単に書ける ● 実は再帰はスタックを使って書ける!
  13. 13. 再帰 ● 関数の中でその関数自身を呼び出すこと ● うまく使うとプログラムが簡単に書ける ● 実は再帰はスタックを使って書ける! ● →Brainf*ckはスタックが書ける!!
  14. 14. 再帰 ● 関数の中でその関数自身を呼び出すこと ● うまく使うとプログラムが簡単に書ける ● 実は再帰はスタックを使って書ける! ● →Brainf*ckはスタックが書ける!! ● →Brainf*ckでは再帰が書ける!!!!
  15. 15. 再帰 ● 関数の中でその関数自身を呼び出すこと ● うまく使うとプログラムが簡単に書ける ● 実は再帰はスタックを使って書ける! ● →Brainf*ckはスタックが書ける!! ● →Brainf*ckでは再帰が書ける!!!! ● サンプル用意するのがめんどくさい&最後に再帰のプログ ラムを書くのでサンプルは省きます
  16. 16. ハノイの塔 以下のルールに従ってすべての円盤を右端の杭に移動さ せられれば完成。 ● 3本の杭と、中央に穴の開いた大きさの異なる複数の円盤 から構成される。 ● 最初はすべての円盤が左端の杭に小さいものが上になる ように順に積み重ねられている。 ● 円盤を一回に一枚ずつどれかの杭に移動させることがで きるが、小さな円盤の上に大きな円盤を乗せることはで きない。 From Wikipedia
  17. 17. ハノイの塔 ● ハノイの塔は再帰的な方法で最短で解けることが知られ ている ● 解法 – 何らかの方法でn-1枚の円盤を左端の杭から中央の杭 に移動させる – 一番大きな円盤を左端の杭から右端の杭に移動させる – 何らかの方法でn-1枚の円盤を中央の杭から右端の杭 に移動させる ● これをBrainf*ckで実装しよう! ● 動かすべき円盤とどこからどこに動かすかを出力する
  18. 18. Brainf*ckでハノイの塔 ● 擬似コードで書くと – Hanoi(n,a,b) //n枚の円盤を左端からa番目の杭からb 番目の杭に移動させる Hanoi(n-1,a,c) Move(n,a,b) Hanoi(n-1,c,b) ● cは{1,2,3}のうちaでもbでもない数 ● Move(k,a,b)はk枚目の円盤を左端からa番目の杭からb番 目の杭に移動させる
  19. 19. Brainf*ckでハノイの塔 ● 「{1,2,3}のうちaでもbでもない数」は、6-a-bで求めら れる ● 再帰の中でMoveという別の関数を呼ぶのに相当する処理 するのは割と難しい – Hanoiに引数をひとつ増やしてHanoi(n,s,a,b)とし て、s=1ならHanoi,s=0ならMoveということにする ● したがって、スタックで実装するときに積むデータの組 はn,s,a,bの四つ組 ● スタックに4個ずつ積んだり取り出したりすることで実装 できる
  20. 20. Brainf*ckでハノイの塔 1.最初にスタックに(n,s,a,b)=(n,1,1,3)を積む 2.スタックの一番上の値を読み、s=0なら6に飛ぶ 3.スタックから取り出した値が(n,1,a,b)だったとすると それを消してスタックに(n-1,1,a,6-a-b),(n,0,a,b), (n-1,1,6-a-b,b)を積む 4.スタックの一番上の値を読み、(1,*,*,*)でないなら3に 戻る 5.スタックの一番上の値を読み、sを1から0にする 6.スタックから取り出した値を出力する。たとえば (3,0,1,3)だったらC 1 3を出力する 7.スタックの一番上の値が(0,*,*,*)でないなら2に戻る
  21. 21. 実際のコード(4枚Ver.) >>>>++++>+>+>++ +<<<[>[<-[[>>>>+>>>>+>>>>+<<<<<<<<<<<<-]>[>>>>+>> >>+>>>>+<<<<<<<<<<<<-]>[>>>>+>>>>+>>>>+<<<<<<<<<< <<-]>[>>>>+>>>>+>>>>+<<<<<<<<<<<<-]<+++++ +>>+>->>>>>>>[<<<<<<<<<<<<+>>>>>>>>>>>>-]>[<<<<<< <<<<<<+>>>>>>>>>>>>-]>[<<<<<<<<<<<<->>>>>>>>>>>>- ]>[<<<<<<<<<<<<+<->>>>>>>>>>>>>-]<<<<<[>>+>+<<<-] >[>+<-]++++++>[<->-]>[<<<+>>>-]<<<<<-]+>-]+++++++ +[>++++++>++++++<<<++++++++>-]>>>>++++[<+++++++ +>-]<<<<<.[-]>>>>.<<.[-]>>.[-]<.[-]++++++++++. [-]<<<<<<<] (454bytes)
  22. 22. まとめ ● 一見Brainf*ckで実装するのが難しそうなものでも要素 要素に分解していくとそこまで大変ではない(こともあ る) ● 今回は入門編でしたがそのうち初級編/中級編/上級編 もやりたいと思います ● 初級編は数値の比較、割り算の商と余り、配列を考えて います
  23. 23. おまけ ● 最近Brainf*ckでメタプログラミングできる拡張bfmeta を作りました ● データメモリとプログラムメモリが同一になっていて、 プログラム実行中にそのプログラム自身を書き換えられ るという仕組み ● それに従い、終了条件をプログラムカウンタの指す値 が0になったら、に変更 ● よくある記号を増やしたりただ置き換えたりするクソみ たいなBrainf*ck拡張と違って、同じ記号でプログラミ ングするのに、はるかに強力な言語になる ● メタプログラミングあんまりやってないのでどんなこと をやると楽しいか教えてください
  24. 24. おわり

×