-
Notifications
You must be signed in to change notification settings - Fork 0
/
day12.hs
78 lines (65 loc) · 2.23 KB
/
day12.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import Data.List
import Data.Maybe
main = do
contents <- readFile "day12_input"
let input = (\(x:xs) -> (x, read xs::Int)) <$> lines contents
ship = (0,0)
pos = (ship, 'E')
-- Part 1
(lastPos, _) = foldl handleIns pos input
res = abs (fst lastPos) + abs ( snd lastPos)
print res
-- Part 2
let wpt = (10, 1)
(lastPos,_) = foldl handleInsPart2 (ship, wpt) input
res = abs (fst lastPos) + abs ( snd lastPos)
print res
handleInsPart2::PosWpt -> Instruction -> PosWpt
handleInsPart2 (ship, wpt) ins =
if isRel ins
then (ship, handleRel wpt ins)
else let (c, i) = ins in case c of 'F' -> handleMovToWpt (ship, wpt) i
'L' -> (ship, handleWptLeft wpt i)
'R' -> (ship, handleWptRight wpt i)
handleMovToWpt::PosWpt -> Int -> PosWpt
handleMovToWpt (ship, wpt) d =
let newShip = (fst ship + d * fst wpt, snd ship + d * snd wpt)
in (newShip, wpt)
handleWptLeft::Coords -> Int -> Coords
handleWptLeft (x,y) 0 = (x, y)
handleWptLeft (x,y) 90 = (-y, x)
handleWptLeft (x,y) 180 = (-x, -y)
handleWptLeft (x,y) 270 = (y, -x)
handleWptRight::Coords -> Int -> Coords
handleWptRight c d = handleWptLeft c (360-d)
handleIns::Pos -> Instruction -> Pos
handleIns (coords, dir) ins =
if isRel ins
then (handleRel coords ins, dir)
else handleMov (coords, dir) ins
handleMov::Pos -> Instruction -> Pos
handleMov (coords, dir) (c, v) =
case c of 'F' -> (handleRel coords (dir, v), dir)
'L' -> (coords, handleLeftTurn dir v)
'R' -> (coords, handleRightTurn dir v)
handleLeftTurn::Direction -> Int -> Direction
handleLeftTurn d v = handleRightTurn d (360-v)
handleRightTurn::Direction -> Int -> Direction
handleRightTurn d v =
let i = fromJust $ d `elemIndex` "NESW"
o = div v 90
in "NESW" !! mod (i+o) 4
handleRel::Coords -> Instruction -> Coords
handleRel (x, y) (c,v) =
case c of 'N' -> (x, y+v)
'S' -> (x, y-v)
'E' -> (x+v, y)
'W' -> (x-v, y)
isRel::Instruction -> Bool
isRel (i,_) =
i `elem` "NSEW"
type Instruction = (Char, Int)
type Coords = (Int, Int)
type Pos = (Coords, Direction)
type PosWpt = (Coords, Coords)
type Direction = Char