Skip to content

Instantly share code, notes, and snippets.

@erantapaa
Last active September 30, 2015 01:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erantapaa/d7758a8ac5a8e226a45b to your computer and use it in GitHub Desktop.
Save erantapaa/d7758a8ac5a8e226a45b to your computer and use it in GitHub Desktop.
L-systems in Haskell
L-systems in Haskell.
===
> import Data.List.Split (splitOn)
> import Data.List
>
> type Rules = [(Char, String)]
>
> -- compute the next generation
> next :: Rules -> String -> String
> next rules [] = []
> next rules (x:xs) =
> case lookup x rules of
> Nothing -> [x] ++ (next rules xs)
> Just y -> y ++ next rules xs
>
> -- another version of next
> next2 :: Rules -> String -> String
> next2 rules xs = concatMap go xs
> where go x = case lookup x rules of
> Nothing -> [x]
> Just y -> y
simplify
===
In this case function `splitOn` and `intercalate` are inverses of each
other. `splitOn` splits a list at the specified delimiter character,
and `intercalate` joins a list of Strings together with a chosen separator
string.
> simplify :: String -> String
> simplify xs = intercalate "F" (map go (splitOn "F" xs))
> where go xs = let count = mod (foldl accumulate 0 xs) 4
> accumulate s '+' = s+1
> accumulate s '-' = s-1
> accumulate s _ = s
> result | count == 0 = ""
> | count == 1 = "+"
> | count == 3 = "-"
> | count == 2 = "++" -- or "--"
> in result
>
> lsystem = [ ('X', "X+YF+"), ('Y', "-FX-Y") ]
>
> test1 = take 4 $ iterate (next lsystem) "FX"
> -- test1 returns: ["FX","FX+YF+","FX+YF++-FX-YF+","FX+YF++-FX-YF++-FX+YF+--FX-YF+"]
>
> test2 = map simplify test1
> -- test2 returns: ["F","F+F+","F+F+F-F+","F+F+F-F+F+F-F-F+"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment