-- Work by: s0678953 Andrew J. McPherson & Alisdair Rankine s0673891 import LSystem --1. join join :: [Command] -> Command join xs = foldr1 (:#) xs --2. split split :: Command -> [Command] split (x :# y) = (split x) ++ (split y) split x = [x] --3. copy copy :: Int -> Command -> Command copy x y =join (take x (repeat y)) -- hexagon hexagon :: Distance -> Command hexagon x = copy 6 (Go x :# Turn 60) -- pentagon pentagon :: Distance -> Command pentagon x = copy 5 (Go x :# Turn 72) --5. polygon polygon :: Distance -> Int -> Command polygon x y = copy y (Go x :# Turn z) where z = (fromIntegral 360) / (fromIntegral y) --6. spiral -- The Guard in the list comprehension ensures that the output distance will not be negative (ie the spiral gets to its centre and begins to grow outwards again.) spiral :: Distance -> Int -> Distance -> Angle -> Command spiral w x y z = join [ Go (w - (y*(fromIntegral(n)))) :# Turn z | n <- [0..x], w>(y*(fromIntegral(n)))] --7. optimise --Puts commands in list, removes those without effect, runs checker then raw optimiser, checks for total optimisation, removes useless commands and rejoins into a single command. optimise :: Command -> Command optimise xs = join (pointlessCommandRemover(optimise'(evenOptimiseCheck (pointlessCommandRemover (split xs))))) -- Checks if Command list is even in length or not and adds negligible commands to help goOptimiser evenOptimiseCheck :: [Command] -> [Command] evenOptimiseCheck xs |even (length xs) = goOptimiser (xs ++ [Sit]) | otherwise = goOptimiser(xs ++ [Sit] ++ [Sit]) -- Carries out raw optimisation goOptimiser :: [Command] -> [Command] goOptimiser [] = [] goOptimiser xs | (take 2 (show (head xs)) == "Go") && (take 2 (show (head(tail xs)))== "Go") = Go ((read(drop 3 (show (head xs)))) + (read(drop 3 (show (head (tail xs)))))) : goOptimiser(drop 1 (tail xs)) | (take 2 (show (head xs)) == "Tu") && (take 2 (show (head(tail xs)))== "Tu") = Turn ((read(drop 5 (show (head xs))))+ (read(drop 5 (show (head(tail xs)))))) : goOptimiser (drop 1 (tail xs)) | otherwise = (head xs) : goOptimiser (tail xs) -- Keeps optimising until it cannot be made more efficient optimise' :: [Command] -> [Command] optimise' xs | evenOptimiseCheck xs == evenOptimiseCheck((evenOptimiseCheck (pointlessCommandRemover xs))) = xs | otherwise = optimise' (evenOptimiseCheck(pointlessCommandRemover xs)) -- Removes commands with no effect and puts them in a list pointlessCommandRemover :: [Command] -> [Command] pointlessCommandRemover xs = [x | x<- (xs), x /= Sit, x /= Turn 0, x /= Go 0, x /= Turn 360] --8. arrowhead arrowhead :: Int -> Command arrowhead x = f x where f 0 = Go 10 f (x+1) = g x :# n :# f x :# n :# g x g 0 = Go 10 g (x+1) = f x :# p :# g x :# p :# f x n = Turn 60 p = Turn (-60) --9. snowflake snowflake :: Int -> Command snowflake x = f x :# p :# p :# f x :# p :# p :# f x :# p :# p where f 0 = Go 10 f(x+1) = f x :# n :# f x :# p :# p :# f x :# n :# f x n = Turn 60 p = Turn (-60) --10. peanoGosper :: Int -> Command peanoGosper x = f x where f 0 = Go 10 f (x+1) = f x :# n :# g x :# n :# n :# g x :# p :# f x :# p :# p :# f x :# f x :# p :# g x :# n g 0 = Go 10 g (x+1) = p :# f x :# n :# g x :# g x :# n :# n :# g x :# n :# f x :# p :# p :# f x :# p :# g x n = Turn 60 p = Turn (-60) --Competition entry completed by Andrew J. McPherson s0678953 --To show the entry please type "display 0.5(compEntry)". compEntry :: Command compEntry = join[ GrabPen yellow, (spiral 5 100000 0.0001 1), Turn (-100), GrabPen orange, Turn (125),(copy 6(Turn (-150) :# Go 10 :# Turn 150 :# Go 10)),Turn (-150),Go 10,Turn (-30),GrabPen black, Go 60, Turn(105),Go 50,Turn 90,(copy 4 (Go 10.0 :# Turn (-10.0))), Go 10, (copy 53 (Go 10.0 :# Turn 5.0)), (copy 4 (Go 10.0 :# Turn (-10.0))), Go 10.0,Turn 85, Go 50, Turn 105, Go 57,GrabPen orange, Turn (-30) ,Go 10,(copy 6(Turn (-150) :# Go 10 :# Turn 150 :# Go 10)), Turn 180, Go 10,(copy 6(Turn (-150) :# Go 10 :# Turn 150 :# Go 10)), Turn 30, GrabPen black, Go 57,Turn 75, Go 32, Go (-32), Turn (-180), Go 50, Turn (90), Go 40, copy 4(Turn (-90):# Go 5 :# Turn 90 :# Go 5 :# Turn 90 :# Go 5 :# Turn (-90) :# Go 10) , Turn 90, Go 30, Turn (-90) , Go 3, Turn 90, Go 12, Turn 90, Go 3, Turn (-90), Go 48,Turn (-90) , Go 3, Turn 90, Go 12, Turn 90, Go 3, Turn (-90), Go 30,Turn 90, Go 7.5, copy 4(Turn (-90):# Go 5 :# Turn 90 :# Go 5 :# Turn 90 :# Go 5 :# Turn (-90) :# Go 10), Go 29.9,Turn 90 , GrabPen metal, (copy 100(Go 130 :# Turn 90 :# Go 0.5 :# Turn 90 :# Go 130 :#Turn (-90) :# Go 0.5 :# Turn (-90) )) , Go 125, Turn (-90), Go 10] yellow = Colour 1.0 0.937254902 0.0 orange = Colour 1.0 0.364705882 0.0 metal = Colour 0.258823529 0.258823529 0.258823529 --For more complex picture dont currently work(!!not part of entry!!) --mixSpiral :: Float ->Pen ->Float -> Pen->Distance -> Int -> Distance -> Angle -> Command --mixSpiral u v w x y z = join [ GrabPen (specialMix (fromIntegral n) u (fromIntegral(x-n)) v) :# Go (w - (y*(fromIntegral(n)))) :# Turn z | n <- [0..x], w>(y*(fromIntegral(n)))] --specialMix :: Float ->Pen ->Float -> Pen -> Pen --specialMix x(Colour a b c) y (Colour a' b' c') = Colour ((x*a+y*a') / (2*y*x)) ((x*b+y*b') / (2*y*x)) ((x*c+y*c') / (2*y*x))