BrainFuck(というプログラミング言語)

cf. どーんとやってみよう – BrainFuck で棒グラフ

なんというか,こんなプログラミング言語があったとは。

見た目にはこれがプログラムだとは思えないんだけど,Wkikipediaにはこうある。

処理系には十分なサイズのbyte型配列とその要素のひとつを指すポインタがある。ポインタを「>」「<」命令で移動させながら、そのポインタが指す値を増減させて処理を進めていく(Hello world参照)。

実用性はほとんど無いように思われるが、これだけでチューリングマシンで実行可能なあらゆるプログラムが記述できる(チューリング完全である)とされている。

つまり,えーと,立派なプログラミング言語だってことか。

見てるだけじゃわからないので,試してみることにする。使ったのはこれ(Windows版)。

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

ちゃんと動いてビックリ(向井さんのとはちょっと違うけど)。

再度Wikipediaによると

実行可能な命令は「8つ」のみである。

1. > ポインタをインクリメントする。ポインタをptrとすると、C言語の「ptr++;」に相当する。

2. < ポインタをデクリメントする。C言語の「ptr–;」に相当。

3. + ポインタが指す値をインクリメントする。C言語の「(*ptr)++;」に相当。

4. – ポインタが指す値をデクリメントする。C言語の「(*ptr)–;」に相当。

5. . ポインタが指す値を出力する。C言語の「putchar(*ptr);」に相当。

6. , 1バイトを入力してポインタが指す値に代入する。C言語の「*ptr=getchar();」に相当。

7. [ ポインタが指す値が0なら、対応する ] までジャンプする。C言語の「while(*ptr){」に相当。

8. ] ポインタが指す値が0でないなら、対応する [ にジャンプする。C言語の「}」に相当。

ということらしい。ついでにいわゆる Hello world プログラムもあった。

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

いろいろいじってると何となくわかってきた。けど,プログラムを読んで動作を理解するのは至難の業だ。動かしてみたほうが速い。

というか,デバッグはどうやってやるんだろう。

キミならどう書く 2.0 – ROUND 3 –

cf. キミならどう書く 2.0 – ROUND 3 –

前のエントリでは話がBrainf*ck(一応伏せ字にする)にいっちゃったけど,こっちが本題。
まったくもって乗り遅れたけど書いてみた。

import System

showStar :: Int -> IO ()
showStar n = do putStrLn $ (show n) ++ " : " ++ (repeatStar n)

repeatStar :: Int -> String
repeatStar n = take n $ repeat '*'

main = do args <- getArgs
          mapM_ showStar $ map read args

実行。

>runghc starbar.hs 3 8 5
3 : ***
8 : ********
5 : *****

OK。いけてるぞ。
でも桁数の違う数が混じると汚いな。

>runghc starbar.hs 3 12 7
3 : ***
12 : ************
7 : *******

まぁいいか。

追記:
(コメントから)
そうか。replicate を使えばいいのか。よし,ついでにポイントフリーにして,

Prelude> let repeatStar = flip replicate '*'
Prelude> :t repeatStar
repeatStar :: Int -> [Char]
Prelude> repeatStar 7
"*******"

本物のプログラマはHaskellを使う

第2回が掲載されている。
けど ITproって会員にならないと記事一覧が見られないらしい。
せっかくだからこのエントリにリンクを作っておこう。

用語の日英対応

『本物のプログラマはhaskellを使う』にでてきた用語の日英対応表をつくってみた。
こういうのは憶えておくと役に立つ,かも。

lazy evaluation 遅延評価,怠惰評価
functional programming 関数型プログラミング
logic programming 論理型プログラミング
probabilistic functional programming 確率的関数プログラミング
Domain Specific Language 特定領域言語,ドメイン特化言語
lambda abstraction ラムダ抽象
anonymous function 無名関数
type inference 型推論
type variable 型変数
context 文脈
type class 型クラス
instance インスタンス
inheritance 継承
subclass サブクラス
module モジュール
import インポート
type synonym 型の同義名,型シノニム
algebraic data type 代数的データ型
type constructor 型構成子,型構築子
data constructor データ構成子,データ構築子
polymorphic type 多相型,多様型
parametric polymorphism パラメータ多相,パラメトリック多相
ad-hoc polymorphism アドホック多相
unboxed array 非ボックス化配列
infix operators 中置演算子
monad モナド
action 動作,アクション
bind 束縛した
do expression do式
do-notation do記法

引数の順序

 cf. 結城浩のHaskell日記 – type宣言

とりとめもない話なんだけど。
エントリのなかに isPrefixOf という関数がでてくる。

xs `isPrefixOf` ys

は文字列 xs が ys のプレフィックスである時に True を返すんだけど,この xs と ys の順序について。

上のように中置形式で書くという前提なら,「xs が ys のプレフィックスのとき True」というのは素直に納得できる。
じゃあ,普通に関数名を前に置いて書いたらどうか。

isPrefixOf xs ys

これって見た目には,どちらかというと「ys が xs のプレフィックスのとき True」,つまり中置き形式のときとは逆じゃないかな。さらに,部分適用してこんな関数を考えてみるとなおさらそんな気がする。

isPrefixOfXS = isPrefixOf "is it prefix of xs?"

いや,こんな関数はあまり有用には思えないからいい例じゃないんだけど。

前置も中置もどちらもおなじ,というのを合わせて考えると,引数の順序もなんだか悩ましいなぁ,と。

『ふつうのHaskellプログラミング』

夕べ帰ったらAmazon.co.jpから届いていた。

[amazonjs asin=”4797373970″ locale=”JP” title=”ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門”]

だけど,今週はちょっと読む時間がない。
入門Haskell―はじめて学ぶ関数型言語』 もまだ消化しきれてないし。
まぁ,焦っても仕方がない。ゆっくり行こう。

高階関数版 filter’

下のエントリは前段でこっちが本題。id:hyukiさんとこにコメントをつけたんだけど,忘れないようにこっちにも書いておく。

filter' f xs = foldr (\m n -> if f m then m:n else n) [] xs

結果。

*Main> take 50 $ filter' odd [1..]
[1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,
57,59,61,63,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99]

major

リスト中に,関数 f(述語って言うの?)を満たす要素のほうが多ければ True をかえす,というのを考えた。all と any の中間みたいなもの。

major f xs = (length $ filter f xs) > (length $ filter (not . f) xs)

結果。

*Main> major odd [1..5]
True
*Main> major even [1..5]
False

地道に数を数えるならこうかな。

major f xs = fst count > snd count
  where count = foldl (\(ct, cf) x -> if f x then (ct+1, cf) else (ct, cf+1)) (0,0) xs
*Main> major odd [1..5]
True
*Main> major even [1..5]
False

はてなグループとコメントについて

id:takatoh:20060604:group についた hyuki さんのコメント。

参加ありがとうございます。ところで、コメントつけるときに「グループに参加」というのはどういう状況でしたか?いちおう誰で も書き込めるようになっていたはずですが…。

たぶん,はてなにログインした状態でコメントしようとしたので,グループに参加するよう促されたのではないかと思います。回避する方法があったのかもしれませんが,別段,断る理由もなかったのでそのまま参加しました。

ところが。

つけたコメントの,名前の部分がリンクになってるんですが,そのリンク先がここじゃなくて Haskellグループ内の日記(使ってないのでカラ)になってしまってます。これはどうしたらいいんだろう。時間があいたら調べてみます。