-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.hs
79 lines (66 loc) · 1.5 KB
/
run.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
79
{-# LANGUAGE BangPatterns, TypeApplications #-}
import AoC
import AoC.Grid
import Data.Bits (xor)
import Data.Ord (comparing)
import Data.Bifunctor (bimap)
import Data.Maybe
import Data.List
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
data Seat = Floor | Empty | Occupied
deriving (Show, Eq)
parse '.' = Floor
parse 'L' = Empty
parse '#' = Occupied
count e = length . filter (e ==)
parseAll = parseMapGrid parse
dirs =
[ (-1, -1)
, (-1, 0)
, (-1, 1)
, (0, -1)
, (0, 1)
, (1, -1)
, (1, 0)
, (1, 1) ]
neighbors g (c, r) =
mapMaybe (flip HashMap.lookup g)
. map (\(dx, dy) -> (c + dx, r + dy))
$ dirs
rule1 g pos s =
case (s, neighbors g pos) of
(Empty, xs)
| count Occupied xs == 0 -> Occupied
(Occupied, xs)
| count Occupied xs >= 4 -> Empty
_ -> s
nearest g (ci, ri) (dx, dy) =
listToMaybe
. mapMaybe id
. dropWhile (== Just Floor)
. takeWhile isJust
. map (flip HashMap.lookup g)
. drop 1
. iterate (bimap (+ dx) (+ dy))
$ (ci, ri)
rule2 g pos s =
case (s, mapMaybe (nearest g pos) dirs) of
(Empty, xs)
| count Occupied xs == 0 -> Occupied
(Occupied, xs)
| count Occupied xs >= 5 -> Empty
_ -> s
step rule g = let !r = HashMap.mapWithKey (rule g) g in r
part1 =
count Occupied
. HashMap.elems
. fixpoint (step rule1)
part2 =
count Occupied
. HashMap.elems
. fixpoint (step rule2)
main = do
input <- parseAll <$> readFile "input.txt"
print (part1 input)
print (part2 input)