X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=src%2Ftask1%2Ftask1.hs;fp=src%2Ftask1%2Ftask1.hs;h=200d538afd1fb1af0a401e81876003baf38fd865;hb=2332d583ac8c5c998732c629cbb16f92b750ab1c;hp=0000000000000000000000000000000000000000;hpb=81c0819fae4ee232c79a92d60aa50256b8b516b3;p=summerofcode2018soln.git diff --git a/src/task1/task1.hs b/src/task1/task1.hs new file mode 100644 index 0000000..200d538 --- /dev/null +++ b/src/task1/task1.hs @@ -0,0 +1,89 @@ +import Data.List (foldl') -- import the strict fold + +-- number of steps +type Step = Int +type Position = (Int, Int) + +data Direction = North | East | South | West + deriving (Enum, Show, Bounded, Eq) + +-- direction, easting, northing +data Mowmaster = Mowmaster { direction :: Direction + , position :: Position + } deriving (Show, Eq) + +data Instruction = Forward Step + | Clockwise + | Anticlockwise + | Comment String + deriving (Show, Eq) + + + +main :: IO () +main = do + instruction_text <- readFile "data/01-mowmaster.txt" + print $ part1 instruction_text + print $ part2 instruction_text + +part1 :: String -> Int +part1 = length . filter (not . isComment) . lines + +part2 :: String -> Int +part2 instruction_text = finalDistance $ executeAll instructions + where instructions = readInstructions instruction_text + executeAll = foldl' execute initialMowmaster + + + +-- Is this line a comment? +isComment :: String -> Bool +isComment ('#':_) = True +isComment _ = False + + +-- Extract the steps from the input string. +readInstructions :: String -> [Instruction] +readInstructions = (map readInstruction) . lines + +readInstruction :: String -> Instruction +readInstruction i = readInstruction' (head i) (tail i) + where readInstruction' 'F' s = Forward (read s) + readInstruction' 'C' _ = Clockwise + readInstruction' 'A' _ = Anticlockwise + readInstruction' _ t = Comment t + + +initialMowmaster = Mowmaster North (0, 0) + + +-- Calculate manhattan distance from start to this state +finalDistance :: Mowmaster -> Int +finalDistance m = (abs e) + (abs n) + where (e, n) = position m + + +-- Make one move +execute :: Mowmaster -> Instruction -> Mowmaster +execute m (Forward s) = m {position = forward s (direction m) (position m)} +execute m Clockwise = m {direction = turnCW (direction m)} +execute m Anticlockwise = m {direction = turnACW (direction m)} +execute m (Comment _) = m + +-- Move in the current direction +forward :: Int -> Direction -> Position -> Position +forward s North (e, n) = (e, n+s) +forward s South (e, n) = (e, n-s) +forward s West (e, n) = (e-s, n) +forward s East (e, n) = (e+s, n) + + +-- | a `succ` that wraps +turnCW :: (Bounded a, Enum a, Eq a) => a -> a +turnCW dir | dir == maxBound = minBound + | otherwise = succ dir + +-- | a `pred` that wraps +turnACW :: (Bounded a, Enum a, Eq a) => a -> a +turnACW dir | dir == minBound = maxBound + | otherwise = pred dir