-- Mark Jones -- 0564129
import LSystem
-- 1.
join :: [Command] -> Command
join x | x == [] = error "No effective command entered!!!"
|otherwise = foldr1 (:#) x
-- i added the guard in for later in the optimise command when something like (Go 20 :# Go (-20)), where no effective command was entered. So rather than giving an unhelpful error, the program gives an explaination for what has happened
-- 2.
split :: Command -> [Command]
split (x :# x2) = split x ++ split x2
split x = [x]
-- 3.
copy :: Int -> Command -> Command
copy n x = join (replicate n x)
-- 4.
hexagon :: Distance -> Command
hexagon d = copy 6 (join [Go d,Turn 60])
-- 5.
polygon :: Distance -> Int-> Command
polygon d n = copy (fromIntegral n) (join [Go d, Turn (360/fromIntegral n)])
-- 6.
spiral:: Distance -> Int -> Distance -> Angle -> Command
spiral max seg decr ang = join (spiral' max seg decr ang )
spiral':: Distance -> Int -> Distance -> Angle -> [Command]
spiral' max seg decr ang = [ Go (max - ((fromIntegral i)*decr)) :# Turn ang | i <- [0..seg], i <=seg, (max - ((fromIntegral i)*decr)) >= 0 ]
-- The guard prevents the spiral from making a very un-pretty reverse spindly shape when the current length is less than 0, because the spiral starts heading in the opposite direction. In that case, the "leftovers" of the spiral function are scrapped.
-- 7.
optimise :: Command -> Command
optimise command = join ( prune (sub (split command)))
sub :: [Command] -> [Command]
sub ([]) = [Go 0]
sub (x:Sit:xs) = sub (x:xs)
sub (x:Go 0:xs) = sub (x:xs)
sub (Sit:xs) = Go 0 : sub xs
sub (Turn x: Turn x2 : xs) = sub (Turn (x+x2):xs)
sub (Go x : Go x2: xs) = sub (Go (x+x2):xs)
sub (Go x: xs) = Go x : (sub xs)
sub (Turn x:xs) = Turn x : (sub xs)
prune :: [Command] -> [Command]
prune [] = []
prune (x:xs) | x == Go 0 = prune xs
| x == Turn 0 = prune xs
|otherwise = x: prune xs
-- 8.
arrowhead :: Int -> Command
arrowhead x = f x
where
f 0 = GrabPen red :# Go 10
f (x+1) = g x :# p :# f x :# p :# g x
g 0 = GrabPen blue :# Go 10
g (x+1) = f x :# n :# g x :# n :# f x
n = Turn (60)
p = Turn (-60)
-- 9.
branch :: Int -> Command
branch x = g x
where
g 0 = GrabPen green :# Go 10
g (x+1) = f x :# n :# Branch ( Branch ( g x ) :# p :# g x )
:# p :# f x
:# Branch ( p :# f x :# g x )
:# n :# g x
f 0 = GrabPen red :# Go 10
f (x+1) = f x :# f x
p = Turn (-22.5)
n = Turn (22.5)
-- 10.
hilbert :: Int -> Command
hilbert x = l x
where
l 0 = GrabPen blue :# Go 10
l (x+1) = p :# r x :# f
:# n :# l x :# f :# l x
:# n :# f :# r x
:# p
r 0 = GrabPen black :# Go 10
r (x+1) = n :# l x :# f
:# p :# r x :# f :# r x
:# p :# f :# l x
:# n
f = GrabPen red :# Go 10
p = Turn (-90)
n = Turn (90)
-- stuff for when i was bored, count this as my competition entries, view it with :
-- >display 0.25 (competition x)
-- where x > 4, the greater the value, the bushier it gets. i would suggest around 6, it will take a minute to create....
competition :: Int -> Command
competition x = a x
where
a 0 = Turn 25
a (x+1) = r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x :# p :# r x
r 0 = Turn 25
r (x+1) = Branch ( g x :# p :# g x :# p :# g x :# p :# g x :# p :# g x :# p :# g x :# p :# g x :# p :# g x :# p :# g x)
g 0 = GrabPen green :# Go 10
g (x+1) = f x :# n :# Branch ( Branch ( g x ) :# p :# g x )
:# p :# f x
:# Branch ( p :# f x :# g x )
:# n :# g x
f 0 = GrabPen red :# Go 10
f (x+1) = f x :# f x
p = Turn (-22.5)
n = Turn (22.5)