HaskellでBrainf*ck
このソースコード、気がつくとかくれんぼしちゃうので
消してしまう前にここに貼っ付けとく。
・hw.txt
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++ ++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]> ++++++++[<++++>-]<+.
・bf.hs
import Char data Command = Inc | Dec | Nxt | Prv | Put | Get | Whl [Command] deriving (Show, Eq) parse :: String -> [Command] parse [] = [] parse (']':cs) = [] parse ('[':cs) = Whl (parse cs) : parse ( rmWhl cs 0 ) where rmWhl :: String -> Int -> String rmWhl (c:cs) nst | c == '[' = rmWhl cs (nst+1) | c == ']' = if nst==0 then cs else rmWhl cs (nst-1) | otherwise = rmWhl cs nst parse (c:cs) | c == '+' = Inc : parse cs | c == '-' = Dec : parse cs | c == '>' = Nxt : parse cs | c == '<' = Prv : parse cs | c == '.' = Put : parse cs | c == ',' = Get : parse cs | otherwise = parse cs type Record = ( [Int], Int ) type State = ( [Command], Record, [Char], [Char] ) get :: Record -> Int get (tape, pnt) = tape !! pnt put :: Record -> Int -> Record put (tape, pnt) num = ((take pnt tape) ++ [num] ++ (drop (pnt+1) tape), pnt) inc, dec, nxt, prv :: Record -> Record inc rec = put rec ((get rec)+1) dec rec = put rec ((get rec)-1) nxt (tape, pnt) = (tape, pnt+1) prv (tape, pnt) = (tape, pnt-1) alteration :: (Record -> Record) -> State -> State alteration f ( (c:cs), rec, input, output ) = eval ( cs, f rec, input, output) eval :: State -> State eval state@( [], _, _, _ ) = state eval state@( Inc:_, _, _, _ ) = alteration inc state eval state@( Dec:_, _, _, _ ) = alteration dec state eval state@( Nxt:_, _, _, _ ) = alteration nxt state eval state@( Prv:_, _, _, _ ) = alteration prv state eval ( Put:cs, rec, input, output ) = eval ( cs, rec, input, output ++ [chr (get rec)] ) eval ( Get:cs, rec, i:is, output ) = eval ( cs, put rec (ord i), is, output ) eval state@( Whl cmds:cs, _, _, _) = evalCs $ pntChk $ evalCmds state where evalCs ( _, w_rec, w_input, w_output) = eval ( cs, w_rec, w_input, w_output) evalCmds ( _, w_rec, w_input, w_output) = eval (cmds, w_rec, w_input, w_output) pntChk w_state@( _, w_rec, _, _ ) = if (get w_rec) == 0 then w_state else pntChk $ evalCmds w_state brainfuck :: String -> String -> String brainfuck source input = getOutput $ eval ( (parse source), ([0,0..], 0), input, "" ) where getOutput ( _, _, _, output ) = output main = do file <- readFile "hw.txt" print $ brainfuck file ""
コンパイル&実行。
$ghc bf.hs -o bf
$./bf => "Hello World!"
やったね!