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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
import Data.List
import Data.Maybe
data Cell = Clr | Obs deriving (Show, Eq)
type Grid = [[Cell]]
type Coo = (Int, Int)
data Dir = U | R | D | L deriving (Show, Eq)
type Guard = (Coo, Dir)
(!?) :: Grid -> Coo -> Maybe Cell
grid !? (row, col)
| row < 0 = Nothing
| row >= length grid = Nothing
| col < 0 = Nothing
| col >= (length $ head grid) = Nothing
| otherwise = Just (grid !! row !! col)
findGuard :: Int -> [[Char]] -> Guard
findGuard r (h:t)
| c == Nothing = findGuard (r + 1) t
| otherwise = ((r, (fromJust c)), U)
where c = elemIndex '^' h
consume :: [Char] -> (Grid, Guard)
consume file =
let toCell = \ln -> case ln of
'#' -> Obs
otherwise -> Clr
grid = map (map toCell) (lines file)
guard = findGuard 0 (lines file) in
(grid, guard)
step :: Grid -> Guard -> Maybe Guard
step grid (coo@(r,c), U)
| cell == Nothing = Nothing
| cell == Just Obs = Just (coo, R)
| cell == Just Clr = Just (ncoo, U)
where
ncoo = (r - 1, c)
cell = grid !? ncoo
step grid (coo@(r,c), R)
| cell == Nothing = Nothing
| cell == Just Obs = Just (coo, D)
| cell == Just Clr = Just (ncoo, R)
where
ncoo = (r, c + 1)
cell = grid !? ncoo
step grid (coo@(r,c), D)
| cell == Nothing = Nothing
| cell == Just Obs = Just (coo, L)
| cell == Just Clr = Just (ncoo, D)
where
ncoo = (r + 1, c)
cell = grid !? ncoo
step grid (coo@(r,c), L)
| cell == Nothing = Nothing
| cell == Just Obs = Just (coo, U)
| cell == Just Clr = Just (ncoo, L)
where
ncoo = (r, c - 1)
cell = grid !? ncoo
(?:) :: Eq a => a -> [a] -> [a]
el ?: arr
| el `elem` arr = arr
| otherwise = el:arr
route :: Grid -> [Coo] -> Guard -> [Coo]
route grid seen guard@(coo, dir)
| nguard == Nothing = coo ?: seen
| otherwise = route grid (coo ?: seen) (fromJust nguard)
where
nguard = step grid guard
route2 :: Grid -> [Guard] -> Bool
route2 grid seen@(guard:_)
| nguard == Nothing = False
| (fromJust nguard) `elem` seen = True
| otherwise = route2 grid ((fromJust nguard):seen)
where
nguard = step grid guard
putObs :: Grid -> Coo -> Grid
putObs grid (r, c) =
let (br,tr:ar) = splitAt r grid
(bc,_:ac) = splitAt c tr in
br ++
[bc ++ [Obs] ++ ac] ++
ar
part1 :: Grid -> Guard -> Int
part1 grid guard =
length $ route grid [] guard
part2 :: Grid -> Guard -> Int
part2 grid guard =
length $
filter (route2A . putObsA) $
route grid [] guard
where
route2A = (flip route2) [guard]
putObsA = putObs grid
main = do
file <- readFile "day06.input"
let (grid, guard) = consume file
putStrLn ("Part 1: " ++ (show $ part1 grid guard))
putStrLn ("Part 2: " ++ (show $ part2 grid guard))
|