Done day 12
[advent-of-code-20.git] / advent12 / src / advent12.hs
1 -- import Debug.Trace
2
3 import Data.Text (Text)
4 -- import qualified Data.Text as T
5 import qualified Data.Text.IO as TIO
6
7 import Data.Attoparsec.Text
8 -- import Data.Attoparsec.Combinator
9 -- import Control.Applicative
10
11
12 data Direction = North | East | South | West
13 deriving (Show, Eq, Ord, Enum, Bounded)
14
15 type Position = (Int, Int) -- (x, y)
16
17 data Action a = N a | S a | E a | W a | L a | R a | F a
18 deriving (Show, Eq, Ord)
19
20 data Ship = Ship { direction :: Direction, position :: Position }
21 deriving (Show, Eq, Ord)
22
23 data ShipW = ShipW { positionW :: Position
24 , waypoint :: Position
25 }
26 deriving (Show, Eq, Ord)
27
28
29
30 main :: IO ()
31 main =
32 do text <- TIO.readFile "data/advent12.txt"
33 let actions = successfulParse text
34 -- print actions
35 print $ part1 actions
36 print $ part2 actions
37
38
39 part1 actions = manhattan (position ship1) start
40 where start = (0, 0)
41 ship0 = Ship {position = start, direction = East }
42 ship1 = foldl act ship0 actions
43
44 part2 actions = manhattan (positionW ship1) start
45 where start = (0, 0)
46 ship0 = ShipW {positionW = start, waypoint = (10, 1)}
47 ship1 = foldl actW ship0 actions
48
49 apAc actions = ship1
50 where start = (0, 0)
51 ship0 = Ship {position = start, direction = East }
52 ship1 = foldl act ship0 actions
53
54 apAcW actions = ship1
55 where start = (0, 0)
56 ship0 = ShipW {positionW = start, waypoint = (10, 1) }
57 ship1 = foldl actW ship0 actions
58
59 act Ship{..} (N d) = Ship { position = dDelta d North position, ..}
60 act Ship{..} (S d) = Ship { position = dDelta d South position, ..}
61 act Ship{..} (W d) = Ship { position = dDelta d West position, ..}
62 act Ship{..} (E d) = Ship { position = dDelta d East position, ..}
63 act Ship{..} (L a) = Ship { direction = d, ..} where d = (iterate predW direction) !! (a `div` 90)
64 act Ship{..} (R a) = Ship { direction = d, ..} where d = (iterate succW direction) !! (a `div` 90)
65 act Ship{..} (F d) = Ship { position = dDelta d direction position, ..}
66 -- where (x, y) = position
67 -- (dx, dy) = (delta direction)
68 -- p' = (x + (d * dx), y + (d * dy))
69
70 actW ShipW{..} (N d) = ShipW { waypoint = dDelta d North waypoint, ..}
71 actW ShipW{..} (S d) = ShipW { waypoint = dDelta d South waypoint, ..}
72 actW ShipW{..} (W d) = ShipW { waypoint = dDelta d West waypoint, ..}
73 actW ShipW{..} (E d) = ShipW { waypoint = dDelta d East waypoint, ..}
74 actW ShipW{..} (L a) = ShipW { waypoint = d, ..} where d = (iterate rotL waypoint) !! (a `div` 90)
75 actW ShipW{..} (R a) = ShipW { waypoint = d, ..} where d = (iterate rotR waypoint) !! (a `div` 90)
76 actW ShipW{..} (F d) = ShipW { positionW = p', ..}
77 where (x, y) = positionW
78 (dx, dy) = waypoint
79 p' = (x + (d* dx), y + (d * dy))
80
81 rotL (x, y) = (-y, x)
82 rotR (x, y) = (y, -x)
83
84 delta North = ( 0, 1)
85 delta South = ( 0, -1)
86 delta East = ( 1, 0)
87 delta West = (-1, 0)
88
89 dDelta dist dir (x, y) = (x + (dist * dx), y + (dist * dy))
90 where (dx, dy) = delta dir
91
92 manhattan (x1, y1) (x2, y2) = abs (x1 - x2) + abs (y1 - y2)
93
94
95 -- | a `succ` that wraps
96 succW :: (Bounded a, Enum a, Eq a) => a -> a
97 succW dir | dir == maxBound = minBound
98 | otherwise = succ dir
99
100 -- | a `pred` that wraps
101 predW :: (Bounded a, Enum a, Eq a) => a -> a
102 predW dir | dir == minBound = maxBound
103 | otherwise = pred dir
104
105 -- Parse the input file
106
107 actionsP = actionP `sepBy` endOfLine
108
109 actionP = choice [nP, sP, eP, wP, lP, rP, fP]
110
111 nP = N <$> ("N" *> decimal)
112 sP = S <$> ("S" *> decimal)
113 eP = E <$> ("E" *> decimal)
114 wP = W <$> ("W" *> decimal)
115 lP = L <$> ("L" *> decimal)
116 rP = R <$> ("R" *> decimal)
117 fP = F <$> ("F" *> decimal)
118
119 successfulParse :: Text -> [Action Int]
120 successfulParse input =
121 case parseOnly actionsP input of
122 Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
123 Right actions -> actions