demo :: IO ()
demo = do
 putStrLn "o o  VLP Multimedia presentations    6 9\n -        proudly presents          \\ o /\n~~~  1D cUrrIeD CaLcUlUs UnIVeRSuM   \\_/\n1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17"
 putStrLn "ScRoLLeR"
 scroller "                                                                                 VLP Jyrää! Todellakin VLP jyrää! VLP jyrää todellakin!                                                                     Ei vaiskaan. Juksasimme."
 putStrLn "StRoBo"
 strobo 50
 putStrLn "Putoava TaLVi-RoBooTTi"
 scroller "                                                                    >-<[8D-*       "
 putStrLn "1D PaRaLLeL CeLLuLaR AuToMaToN"
 ca1d 50 automaton
 putStrLn "ScRoLLeR"
 scroller "                                                                          Greetings to all rEaL eLiTeZ :                                                                              pyynö                                                                                  TWN RuLeZ!"
 putStrLn "AnOtHeR 1D PaRaLLeL CeLLuLaR AuToMaToN"
 caLoop automaton
 where 
 automaton = stringToBool "10101101010110110111010110101011011011010101010101011100001010101000101110110"

strobo :: Int -> IO()
strobo 0 = do
 putStr ((take 80 (charList ' ')) ++ "\r")
strobo i = do
 putStr ((take 80 (charList ' ')) ++ "\r")
 putStr ((take 80 (charList '#')) ++ "\r")
 strobo (i-1)

charList :: Char -> String
charList a = a:(charList a) 

scroller :: String -> IO()
scroller [] = do
 putStr ((take 80 (charList ' ')) ++ "\r")
scroller (s:ss) = do
 putStr ((take 80 ((s:ss) ++ (charList ' '))) ++ "\r")
 scroller ss

stringToBool :: String -> [Bool]
stringToBool [] = []
stringToBool ('1':as) = (True:(stringToBool as))
stringToBool ('0':as) = (False:(stringToBool as))

boolToString :: [Bool] -> String
boolToString [] = []
boolToString (True:as) = ('#':(boolToString as))
boolToString (False:as) = (' ':(boolToString as))

ca1d :: Int -> [Bool] -> IO()
ca1d 0 a = do
 putStr ((take 80 (charList ' ')) ++ "\r")
ca1d i a = do
 putStr ((boolToString a) ++ "\r")
 ca1d (i-1) (ca a)

caLoop :: [Bool] -> IO()
caLoop a = do
 putStrLn ((boolToString a))
 caLoop (ca a)

ca :: [Bool] -> [Bool]
ca (a1:(a2:as)) = cai False a1 a2 as

cai :: Bool -> Bool -> Bool -> [Bool] -> [Bool]
cai a0 a1 a2 [] = (testCell a0 a1 a2:[testCell a1 a2 False])
cai a0 a1 a2 (a3:as) = ((testCell a0 a1 a2):(cai a1 a2 a3 as))

testCell :: Bool -> Bool -> Bool -> Bool
testCell a0 a1 a2 = ((a1==True && not (a0 && a2)) || (a1==False && (a0 || a2)))
