module Control.Comonad.Sheet.Examples where
import Control.Comonad.Sheet
import Control.Applicative ( (<$>), (<*>) )
import Data.List ( intersperse )
import Data.Bool ( bool )
import Data.Stream ( Stream , repeat , (<:>) )
import qualified Prelude as P
import Prelude hiding ( repeat , take )
pascal :: Sheet2 Integer
pascal = evaluate . sheet 0 $
repeat 1 <:> repeat (1 <:> pascalRow)
where pascalRow = repeat $ cell above + cell left
diagonalize :: Sheet2 a -> [[a]]
diagonalize =
zipWith P.take [1..]
. map (map extract . P.iterate (go (above & right)))
. P.iterate (go below)
fibLike :: Sheet3 Integer
fibLike = evaluate $ sheet 0 $
fibSheetFrom 1 1 <:> repeat (fibSheetFrom (cell inward + 1) (cell inward))
where fibSheetFrom a b = (a <:> b <:> fibRow) <:>
repeat (cell above <:> (1 + cell above) <:> fibRow)
fibRow = repeat $ cell (leftBy 1) + cell (leftBy 2)
data Cell = X | O deriving ( Eq , Show )
type Universe = Sheet3 Cell
type Ruleset = ([Int],[Int])
life :: Ruleset -> [[Cell]] -> Universe
life ruleset seed = evaluate $ insert [map (map const) seed] blank
where blank = sheet (const X) (repeat . tapeOf . tapeOf $ rule)
rule place = case (neighbors place `elem`) `onBoth` ruleset of
(True,_) -> O
(_,True) -> cell inward place
_ -> X
neighbors = length . filter (O ==) . cells bordering
bordering = map (inward &) (diagonals ++ verticals ++ horizontals)
diagonals = (&) <$> horizontals <*> verticals
verticals = [above, below]
horizontals = map d2 [right, left]
onBoth :: (a -> b) -> (a,a) -> (b,b)
f `onBoth` (x,y) = (f x,f y)
conway :: [[Cell]] -> Universe
conway = life ([3],[2,3])
printLife :: Int -> Int -> Int -> Universe -> IO ()
printLife c r t = mapM_ putStr
. ([separator '┌' '─' '┐'] ++)
. (++ [separator '└' '─' '┘'])
. intersperse (separator '├' '─' '┤')
. map (unlines . map (("│ " ++) . (++ " │")) . frame)
. take (rightBy c & belowBy r & outwardBy t)
where
separator x y z = [x] ++ P.replicate (1 + (1 + c) * 2) y ++ [z] ++ "\n"
frame = map $ intersperse ' ' . map (bool ' ' '●' . (O ==))
glider :: Universe
glider = conway [[X,X,O],
[O,X,O],
[X,O,O]]
spaceship :: Universe
spaceship = conway [[X,X,X,X,X],
[X,O,O,O,O],
[O,X,X,X,O],
[X,X,X,X,O],
[O,X,X,O,X]]