never executed always true always false
1 {-|
2 Module: Y2016.D01
3 Description: Advent of Code Day 01 Solutions.
4 License: MIT
5 Maintainer: @tylerjl
6
7 Solutions to the day 01 set of problems for <adventofcode.com>.
8 -}
9 module Y2016.D01
10 ( blockDistance
11 , visitedTwice
12 ) where
13
14 import Data.List (foldl')
15 import qualified Data.Set as Set
16
17 -- | Cardinal direction for movement
18 data Direction
19 = North
20 | East
21 | South
22 | West
23 deriving (Enum)
24
25 -- | (x, y) coordinates
26 type Coordinates = (Int, Int)
27
28 -- | Find number of blocks traveled per list of instructions
29 blockDistance
30 :: String -- ^ Input of directions
31 -> Int -- ^ Number of blocks traveled
32 blockDistance = blocks . foldl' travel (0, 0) . mapRoute
33
34 -- | Find first block that is visited twice
35 visitedTwice
36 :: String -- ^ Input of directions
37 -> Maybe Int -- ^ Possible block that is visited twice
38 visitedTwice = navigate (0, 0) Set.empty . mapRoute
39 where
40 navigate point set (path:xs)
41 | Set.member point' set = Just $ blocks point'
42 | otherwise = navigate point' (Set.insert point' set) xs
43 where
44 point' = travel point path
45 navigate _ _ _ = Nothing
46
47 -- | Translate an input string into a list of movement `Direction`s
48 mapRoute
49 :: String -- ^ Input string
50 -> [Direction] -- ^ List of `Direction`s
51 mapRoute = toRoute North . map (toPath . filter (not . (==) ',')) . words
52 where
53 toRoute orientation ((lr, distance):xs) =
54 replicate distance orientation' ++ toRoute orientation' xs
55 where
56 orientation' = turn lr orientation
57 toRoute _ [] = []
58
59 -- | Calculate the number of blocks from the origin
60 blocks
61 :: Coordinates -- ^ Current `Coordinates`
62 -> Int -- ^ Number of blocks that `Coordinate` lies from the origin
63 blocks (x, y) = abs x + abs y
64
65 -- | Move along a given direction
66 travel
67 :: Coordinates -- ^ Initial `Coordinates`
68 -> Direction -- ^ `Direction` to move towards
69 -> Coordinates -- ^ New `Coordinates`
70 travel (x, y) d =
71 case d of
72 North -> (x, succ y)
73 East -> (succ x, y)
74 South -> (x, pred y)
75 West -> (pred x, y)
76
77 -- | Translate a movement instruction to an intermediate form
78 toPath
79 :: String -- ^ Raw input instruction
80 -> (Char, Int) -- ^ `Tuple` consisting of movement direction and
81 -- ^ distance
82 toPath (direction:steps) = (direction, read steps)
83 toPath [] = (' ', 0)
84
85 -- | Determine new direction after turning Left or Right
86 turn
87 :: Char -- ^ 'L'eft or 'R'right
88 -> Direction -- ^ Initial `Direction`
89 -> Direction -- ^ New `Direction`
90 turn 'R' West = North
91 turn 'L' North = West
92 turn 'R' d = succ d
93 turn 'L' d = pred d
94 turn _ d = d