Your SlideShare is downloading. ×
実用Brainf*ckプログラミング入門編
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

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

4,488
views

Published on

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

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


0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,488
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
12
Comments
0
Likes
6
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

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