-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay11.hs
74 lines (59 loc) · 1.56 KB
/
Day11.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
module Day11 where
import Data.Array
data Cell = Empty | Occupied | Floor
deriving (Eq, Show)
isCell 'L' = True
isCell '#' = True
isCell '.' = True
isCell _ = False
toCell 'L' = Empty
toCell '#' = Occupied
toCell '.' = Floor
instance Read Cell where
readsPrec _ (c:rest) = [(toCell c, rest)]
readList input = [(map toCell cells, rest)]
where (cells, rest) = span isCell input
toChar Empty = 'L'
toChar Occupied = '#'
toChar Floor = '.'
type State = Array (Int, Int) Cell
parse :: String -> State
parse input = listArray ((1, 1), (width, height)) $ concat lists
where
lists :: [[Cell]]
lists = map read $ lines input
width = length $ head lists
height = length lists
render :: State -> String
render state = unlines chunks
where
(_, (width, _)) = bounds state
chars = map toChar $ elems state
chunks = chunk width chars
chunk n [] = []
chunk n xs = curr:(chunk n rest)
where
(curr, rest) = splitAt n xs
n (x, y) = (x, y-1)
s (x, y) = (x, y+1)
w (x, y) = (x-1, y)
e (x, y) = (x+1, y)
ne = n . e
nw = n . w
se = s . e
sw = s . w
directions x = map ($ x) [n, ne, e, se, s, sw, w, nw]
(!?) arr ix =
if inRange (bounds arr) ix
then Just (arr ! ix)
else Nothing
tick :: State -> State
tick curr = array (bounds curr) $ map nextCell $ assocs curr
where
occupiedAdjacent ix =
length $ filter (== (Just Occupied)) $ map ((!?) curr) $ directions ix
nextCell c@(ix, Empty)
| occupiedAdjacent ix == 0 = (ix, Occupied)
nextCell c@(ix, Occupied)
| occupiedAdjacent ix >= 4 = (ix, Empty)
nextCell x = x