-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay11.roc
179 lines (136 loc) · 5.19 KB
/
Day11.roc
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
interface Day11 exposes [ output ] imports [ Map2, TestUtil ]
output : List I64 -> List (List I64)
output = \puzzleInput ->
testInfo = Map2.info testInput 0
puzzleInfo = Map2.info puzzleInput 0
[ TestUtil.verify 11 1 1 (occupied testInput testInfo ) 37
, TestUtil.show 11 1 (occupied puzzleInput puzzleInfo)
, TestUtil.verify 11 2 1 (occupiedV2 testInput testInfo ) 26
, TestUtil.show 11 2 (occupiedV2 puzzleInput puzzleInfo)
]
# first part
occupied : List I64, Map2.Inf2 -> I64
occupied = \map, inf ->
res = step map inf
if res.changed then
occupied res.dstMap inf
else
countOccupied res.dstMap
step : List I64, Map2.Inf2 -> StepResult
step = \map, inf ->
stepHelper map inf False map 0 0
StepResult : { changed : Bool, dstMap : List I64 }
stepHelper : List I64, Map2.Inf2, Bool, List I64, I64, I64 -> StepResult
stepHelper = \map, inf, changed, dstMap, y, x ->
if y < inf.rows then
if x < inf.cols then
oldSeat = Map2.getI map inf y x
newSeat =
when oldSeat is
76 ->
if occupiedNeighbours map inf y x == 0 then
35
else
oldSeat
35 ->
if occupiedNeighbours map inf y x >= 4 then
76
else
oldSeat
_ ->
oldSeat
if oldSeat == newSeat then
stepHelper map inf changed dstMap y (x + 1)
else
newMap = Map2.setI dstMap inf y x newSeat
stepHelper map inf True newMap y (x + 1)
else
stepHelper map inf changed dstMap (y + 1) 0
else
{ changed, dstMap }
occupiedNeighbours : List I64, Map2.Inf2, I64, I64 -> I64
occupiedNeighbours = \map, inf, y, x ->
(occupiedNum map inf (y - 1) (x - 1)) +
(occupiedNum map inf (y - 1) x ) +
(occupiedNum map inf (y - 1) (x + 1)) +
(occupiedNum map inf y (x - 1)) +
(occupiedNum map inf y (x + 1)) +
(occupiedNum map inf (y + 1) (x - 1)) +
(occupiedNum map inf (y + 1) x ) +
(occupiedNum map inf (y + 1) (x + 1))
occupiedNum : List I64, Map2.Inf2, I64, I64 -> I64
occupiedNum = \map, inf, y, x ->
if Map2.getI map inf y x == 35 then 1 else 0
countOccupied : List I64 -> I64
countOccupied = \map ->
List.keepIf map (\c -> c == 35) |> List.len
# second part
occupiedV2 : List I64, Map2.Inf2 -> I64
occupiedV2 = \map, inf ->
res = stepV2 map inf
if res.changed then
occupiedV2 res.dstMap inf
else
countOccupied res.dstMap
stepV2 : List I64, Map2.Inf2 -> StepResult
stepV2 = \map, inf ->
stepV2Helper map inf False map 0 0
stepV2Helper : List I64, Map2.Inf2, Bool, List I64, I64, I64 -> StepResult
stepV2Helper = \map, inf, changed, dstMap, y, x ->
if y < inf.rows then
if x < inf.cols then
oldSeat = Map2.getI map inf y x
newSeat =
when oldSeat is
76 ->
if occupiedNeighboursV2 map inf y x == 0 then
35
else
oldSeat
35 ->
if occupiedNeighboursV2 map inf y x >= 5 then
76
else
oldSeat
_ ->
oldSeat
if oldSeat == newSeat then
stepV2Helper map inf changed dstMap y (x + 1)
else
newMap = Map2.setI dstMap inf y x newSeat
stepV2Helper map inf True newMap y (x + 1)
else
stepV2Helper map inf changed dstMap (y + 1) 0
else
{ changed, dstMap }
occupiedNeighboursV2 : List I64, Map2.Inf2, I64, I64 -> I64
occupiedNeighboursV2 = \map, inf, y, x ->
(occupiedNumV2 map inf (y - 1) (x - 1) (-1) (-1)) +
(occupiedNumV2 map inf (y - 1) x (-1) 0 ) +
(occupiedNumV2 map inf (y - 1) (x + 1) (-1) 1 ) +
(occupiedNumV2 map inf y (x - 1) 0 (-1)) +
(occupiedNumV2 map inf y (x + 1) 0 1 ) +
(occupiedNumV2 map inf (y + 1) (x - 1) 1 (-1)) +
(occupiedNumV2 map inf (y + 1) x 1 0 ) +
(occupiedNumV2 map inf (y + 1) (x + 1) 1 1 )
occupiedNumV2 : List I64, Map2.Inf2, I64, I64, I64, I64 -> I64
occupiedNumV2 = \map, inf, y, x, dy, dx ->
when Map2.getI map inf y x is
35 -> 1
76 -> 0
46 -> occupiedNumV2 map inf (y + dy) (x + dx) dy dx
_ -> 0
# test data
testInput : List I64
testInput =
[ 76, 46, 76, 76, 46, 76, 76, 46, 76, 76, 10
, 76, 76, 76, 76, 76, 76, 76, 46, 76, 76, 10
, 76, 46, 76, 46, 76, 46, 46, 76, 46, 46, 10
, 76, 76, 76, 76, 46, 76, 76, 46, 76, 76, 10
, 76, 46, 76, 76, 46, 76, 76, 46, 76, 76, 10
, 76, 46, 76, 76, 76, 76, 76, 46, 76, 76, 10
, 46, 46, 76, 46, 76, 46, 46, 46, 46, 46, 10
, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 10
, 76, 46, 76, 76, 76, 76, 76, 76, 46, 76, 10
, 76, 46, 76, 76, 76, 76, 76, 46, 76, 76, 10
]