import Control.Monad.State {- 状態モナドを使う.状態は亀の向いている方向 -} type Order = Int type Direction = (Int, Int) data L = P | M | F deriving Show -- P が + に M が - にそれぞれ対応 type LSystem = [L] p = (P:) m = (M:) f = (F:) x, y :: Order -> (LSystem -> LSystem) x 0 = id x (n+1) = p . y n . f . m . x n . f . x n . m . f . y n . p -- + Y F - X F X - F Y + y 0 = id y (n+1) = m . x n . f . p . y n . f . y n . p . f . x n . m -- - X F + Y F Y + F X - {- *Main> x 0 [] [] *Main> x 1 [] [P,F,M,F,M,F,P] *Main> x 2 [] [P,M,F,P,F,P,F,M,F,M,P,F,M,F,M,F,P,F,P,F,M,F,M,F,P,M,F,M,F,P,F,P,F,M,P] -} hilbert :: Order -> LSystem hilbert n = x n [] translate :: LSystem -> State Direction ShowS translateP,translateM,translateF :: State Direction ShowS -> State Direction ShowS translateP sm = modify left >> sm translateM sm = modify right >> sm translateF sm = get >>= \ d -> sm >>= \ ss -> return (fc d . ss) where fc (dx,dy) = shows dx.space.shows dy.space.showString "rlineto".newline left, right :: Direction -> Direction left (dx,dy) = (-dy,dx) right (dx,dy) = (dy,-dx) space, newline :: ShowS space = showString " " newline = showString "\n" translate [] = return id translate (P:ls) = translateP (translate ls) translate (M:ls) = translateM (translate ls) translate (F:ls) = translateF (translate ls) moveto :: Int -> Int -> ShowS moveto x y = shows x . space . shows y . space . showString "moveto" . newline stroke :: ShowS stroke = showString "stroke" . newline drawHilbert :: Int -> Int -> ShowS drawHilbert sz n = moveto o o . evalState (translate $ hilbert n) d0 . stroke where d0 = (sz `div` 2 ^ n, 0) o = sz `div` 2 ^ (n+1) main = putStrLn $ drawHilbert 256 5 ""