+811
2024/day12.livemd
+811
2024/day12.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 12
4
+
5
+
```elixir
6
+
Mix.install([:kino_aoc, :range_set])
7
+
```
8
+
9
+
## Section
10
+
11
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxMiIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
12
+
13
+
```elixir
14
+
{:ok, puzzle_input} =
15
+
KinoAOC.download_puzzle("2024", "12", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
16
+
```
17
+
18
+
<!-- livebook:{"output":true} -->
19
+
20
+
```
21
+
{:ok,
22
+
"KKKKKKZZZZZZZZDDQQQQXXXXXXXXXXXXTTTTTTTTTTTTDHHHHHHHHHHHHHHHHHGGGGGGPPPGUUGGXXGGGGGGJJJJJJJJJIIIIIIIIIIIIIIIIIIIIDIIIIIIIIIIIKIIIIIIIIIIIIIM\nKKKKKKZZZZZZZDDDQQQQXXCXXXXXXXXXTTTTTTTTTTTTTHHHHHHHHHHHHHHHHHGGGGGGGGPGUUGGGGGGGGGJJJJJJJJIIIIIIIIIIIIIIIIIIVVVIDDIIIIIIIKKKKIIIIIIIIIIIIMM\nKKKKKZZZZZZZZZZQQQQQQXCCCXXXXXXTTTTTTTTTTTTTTTHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGJJJJJJJJJJIIIIIIIIIIIIIIIIIIVIIIIDIHIIIIIIIKKIIIIIIIIIIIIMM\nKKKKKZZZZZZZZEEHQQQYQQZCCCCXXXTTTTTTTTTTTTTTHHHIIIIHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGJJJJJJJJIIIIIIIIKKKKKKIIIIIVIIIIDHHIIIIIIIIKIIIIIIIIIIIIIM\nKKKKKKOOEZEEEEHHQQQYYCCCCCCTTTTTTTTTTTTTTTTTVVVIIIIHHHHHHBBBBGGGGGGGGGGGGGGGGGGGGJJJJJJJJJIIIIIIIBCKKKKKIIIIIIIIHHHHHIIIIIIIIIIIIIIIIIIIMMMM\nKKKKKOOEEEEEEEHHHQQYYCCCCCCCCCTTTTTTTTTTTOOTTIIIIIHHHHHHHHHBBBGGGGGGGGGGGGGGGGGGGJJJJJJJJJIIIIIBBBCKKKKKKKIIIIIHHHHHIIIIIIIIIIIIIIIIIIIIIIMM\nKKKKKKOGGEEEGHHHHQDDYYCCCCCCCOOTTTTTTTTTTTIDIIIIIIIHHHHHHBBBBBGGGGGGGGGGGGGGGGGGGGJJJJJJJJIIIIBBBBKKKKKKKKIKIIIBHHHHHIIIIIIIIIIIIIIIIIIIIIIM\nKKKKTKOOGEGGGHGHDDDDDYYYCCCCCOOTTTTTTTTTTIIIIIIIIIIHHHHHBBBBBBGGGGGJGGGQGGLGGGGGGJJJJJJRRJJJBBBBKKKKKKKKKKKKKKFHHHHHHHIHHIIIIIRIIIIIIIIIIMMM\nKRRRVOOGGGGGGGGGDDDDPDDYDSSCCCOOOTTOTTTTTIIIIIIIIIIHHHBHBBBBBBGGGGGJGJJGGGGGGGGGGJJJJJRRRRRWBBBBBBVKKKKKKKKKKTHHHHHHHHHHIIIIIIIIIIIIIIGIIMMM\nYVRVVOOGGGGGGGDDDDDDDDDDDSSCCOOOOOOOTOOOIIIIIIIIIIIHHBBBBBBBBBGGGGGJJJJJGGGCGGFFGFFJRRRRRRRWWBBBBBBKKKKKKKKKKKHHHHHHHHHFFIIIIIIIIIIIIIGIVVMM\nYVRVVVVGGGGGGGDDDDDDDDDDDDDCCOOOOOOOOOOOIIIIIIIIIIIHHHBBBBBBBBBBGGJJJJJJJJJGGGFFFFRRRRRRRRRRRBBBBBKKKKKKKKKKKKKHHHHHHHHFIIIIIIIIIIIIIIIIVVVM\nYVVVVVVVVGGGGGGDDDDDDDDDDDDOOOOOOOOOOOOOOIIIIIIEEIIHHHOBBBBBBBBBBGJJJJJJJJJFFFFFFFFFRRRRRRRRRRBBBBKBKKKKKKKKKKKHHHHHHFFFFIIFIIIIZIIAIIIIVVMM\nVVVVVVVVVGGGGGGDDDDDDDDDDDOOOOOOOOOOOOOOOOOOOIOOEJJHHHOBBBBBBBBBBEEJEEEEEFFFFFFFFFFFRRRRRRRNBBBBBBBBKKKKKKKKKKRHHHHHHFFFFFFFIIIIIIIIBBIIVMMM\nVVVVVVVVVGGGGGDDDDDDDDDDDDEOOOOOOOOOOOOOOOOOOOOOEEJHHOOOBBBBGGGGBEEEHEEXFFFFFFFFFFFFRRRRRRBNBBBBBBBBKKKKKKKKKKHHHHHHHFFFFFFFIIIIIIIIBBVVVMMM\nVVVVVVVVGGGGGDPDDDDDDDDDDDEEOOOOOOOOOOOOOOOOOOOOEEJEOOOOBGGGGGGGHEEEEEEFFFLFFFFFFFFRRRRRRRBBBBBBBBBBBKKKKKKKKFHHHHHFFFFFFFFIIIIIIIIIIVVVVVMM\nVVVVVVVVGGGGGDDDDDDDDDDDDDDEOOOOOOOOGOOOOOEOIIOOEEEEOOOOOGGGGGGGEEEEEEEFFFFFFFFFFFFFRDRRXXBBBBBBBBBBBKKKKKKKKKBBHHHHFFFFFFFIIIIIIIIIVVVVVVLM\nVVVVVVVVWGGGGDDDDDDDDDDDDEEEOOOOOOGGGOOOOOOIIIIIEEOOOOBOOGGGGGGGUEEEEEGUFFFFFFFFFFFFDDDDMMSBBBBBBBBBBBBBKKKKKKBBBHHFFFFFFFFIIIIINNWIVVVVVVLL\nVVVVVVZZZFGGGRDDDDDDDDDDDEOOOOOOOFFFGOGOOIIIBIBBBEOBBBBBBGGGGGGGEEEEEGGUUFFFFFFFFFFFDDDDDMMMBBBBBBBBBBBKKKKKKBBBBHHFFFFFFFFFIINNNNNPPVVVVLLL\nVVVZZZZZZZIGRRADADDDDDDDDEOEEOYYGFFGGOGGGIIIBBBBBEBBBBBBBGGGGGGGFEEEGGGGUUFFFFFFFFFHDVVVVVVMBBBBBBBBBBBKKKKBBBBBBBBBFFFFFFFRRRRNNNNPPVVLLLLL\nVVZZZZZZZZZRRRADAADEEEDDDEEEEOYYGGGGGGGGGGIBBBBBBBBBBBBBBGGGGGGGEEEEBGGGUUFFFFFFFFFHHVVVVVVMBBBBBBBBBPBKKBBBBBBBBBBFFFFFFFFFRBRNNNNNNNVLLLLL\nVZZZZZBZZZNAAAAAAAAEEEEEEEEEGGYYGGGGGGGGGIIBBBBBBBBBBBBBBGGGGGFFFEEBBGGGGCFFFFFFFFFHHVVVVVVMBBBBBBBMMMMMBBBBBBBGBBBFFFFFFFGGBBBNNNNNLLLLLLLL\nBBBBBBBZZNNNAAAAAAEEEEEEGEEEEGYYGGGGGGGIIIIBBBBBBBBBBBBBBGGGGGFFCCCBGGGCCCFCCWWWWWWWHVVVVVVMMBBBMMMMMMMMBBBBBBBGBGGTTFFFFFFFFBBNNNNNLLLLLLLL\nJBBBBBBBZZNAAAAAAAAAAGGGGGGEGGGGGGGGGGGGGIHDBBBBBBBBBBBBBBFFFFFCCCCCGGGCCKCCCWHHHHHHHVVVVVVMMVVVVVVMMMMMBBBBBBGGBGGTFFFFTFFFFBBBBBBBBBLLLLLL\nJJJBBBBBBAAAAAAAAAAAGGGGGGGEGGGGGGGGGGGGIIHDBBBBBBBBBBBBBBBBFFFCZCCCCCCCCCCCCHHHHHHHHVVVVVVMMVVVVVVMMMMMBBBBBBGGGGGTTFFTTFFFBBBBBBBBBBLLLLLL\nJJJBBBBAAAAAAAAAAAAAGGGGGGGGGGGGGGGGGGGGIHHDHHHHBBBBBBSSSSFFFFFCCCCCCCCCCCCCCHHHHHHHHVVVVVVHHVVVVVVMMMMMBBBBBBGGGGGTTTTTTFHFBBBBBBBBBBBLBBLV\nJJJJJJAAAAAAAAAAAAAAGGGGGGGGGGGGGGGGGGGHHHHHHHHHHIJJJJJSSSSFFFCCFFCCCCCCCCCCCHHHHHHHHVVVVVVVVVVVVVVMMMMMMBBBBGGGGGGGGGTTTLLBBBBBBBBBBBBBBBBV\nJJJJJJAAAAAAAAAAAAAAGAAGGGGGGGGGGGGGGGGHHHHHHHHHHJJJHJSSSSSFFFFFFCCCCCCCCCCCCHRHHHHHHVVVVVVVVVVVVVVGMMMMMBBBBGGGGGGGGGTTLLLLLLBBBBBBBBBBBBBB\nJJJJJJAAAAAAAAAAAAAAAAGGGGGGGGHGGGGGGGGHHHHHHHHHHJJJJJJJSJSFFFFFCCCCCCCCCCCCCCHHHHHHHVVVVVVVVVVVVVVGGMMCMBBBGGGGGGGGPGGGLLZLLLBBBBBBBBBBBBBB\nJJJJJJAAAAAAAAAAAAAAGAGGGGGGGGGGGGZZGHGHHHHHHHHHJJJJJJJJJJSFFFFFCCCCCCCCCCCCCCHHHHHHHHHOHHOOMVVVVVVGGJGGIBBBTGGGGGGTGGGLLLLLLLLBBBBBBBBBBBBB\nJJJJJAA" <> ...}
23
+
```
24
+
25
+
```elixir
26
+
map =
27
+
puzzle_input
28
+
|> String.split("\n", trim: true)
29
+
|> Enum.with_index()
30
+
|> Enum.flat_map(fn {row, y} ->
31
+
row
32
+
|> String.split("", trim: true)
33
+
|> Enum.with_index()
34
+
|> Enum.map(fn {plant, x} -> {{x, y}, plant} end)
35
+
end)
36
+
|> Map.new()
37
+
```
38
+
39
+
<!-- livebook:{"output":true} -->
40
+
41
+
```
42
+
%{
43
+
{18, 103} => "H",
44
+
{76, 13} => "F",
45
+
{61, 121} => "X",
46
+
{112, 138} => "T",
47
+
{37, 47} => "U",
48
+
{65, 63} => "G",
49
+
{77, 129} => "E",
50
+
{120, 47} => "L",
51
+
{38, 2} => "T",
52
+
{1, 26} => "J",
53
+
{116, 69} => "W",
54
+
{124, 56} => "O",
55
+
{83, 76} => "N",
56
+
{117, 125} => "Q",
57
+
{100, 134} => "W",
58
+
{78, 139} => "D",
59
+
{32, 15} => "O",
60
+
{103, 106} => "N",
61
+
{30, 113} => "J",
62
+
{123, 104} => "W",
63
+
{68, 134} => "Q",
64
+
{124, 60} => "O",
65
+
{89, 14} => "R",
66
+
{35, 30} => "E",
67
+
{37, 53} => "H",
68
+
{77, 130} => "E",
69
+
{2, 132} => "Q",
70
+
{4, 5} => "K",
71
+
{8, 50} => "X",
72
+
{78, 98} => "Y",
73
+
{101, 62} => "X",
74
+
{98, 136} => "W",
75
+
{95, 56} => "D",
76
+
{74, 12} => "F",
77
+
{17, 138} => "F",
78
+
{102, 74} => "S",
79
+
{11, 39} => "P",
80
+
{131, 5} => "I",
81
+
{65, 43} => "S",
82
+
{22, 38} => "R",
83
+
{14, 86} => "N",
84
+
{139, 46} => "U",
85
+
{12, 135} => "Q",
86
+
{65, 131} => "A",
87
+
{49, 117} => "O",
88
+
{20, 41} => "D",
89
+
{29, 25} => "G",
90
+
{86, 10} => "R",
91
+
{83, ...} => "I",
92
+
{...} => "G",
93
+
...
94
+
}
95
+
```
96
+
97
+
```elixir
98
+
defmodule Garden do
99
+
def plots(map) do
100
+
map
101
+
|> Enum.group_by(&elem(&1, 1), &elem(&1, 0))
102
+
|> Enum.flat_map(fn {kind, pts} ->
103
+
for parcel <- parcels(MapSet.new(pts), []) do
104
+
{kind, parcel}
105
+
end
106
+
end)
107
+
end
108
+
109
+
def parcels(set, acc) do
110
+
case Enum.take(set, 1) do
111
+
[] ->
112
+
acc
113
+
114
+
[p] ->
115
+
{parcel, rest} = flood(p, MapSet.new(), set)
116
+
117
+
parcels(rest, [parcel | acc])
118
+
end
119
+
end
120
+
121
+
def flood({x, y} = curr, visited, potential) do
122
+
visited = MapSet.put(visited, curr)
123
+
potential = MapSet.delete(potential, curr)
124
+
125
+
for next <- [
126
+
{x - 1, y},
127
+
{x + 1, y},
128
+
{x, y - 1},
129
+
{x, y + 1}
130
+
],
131
+
next in potential,
132
+
reduce: {visited, potential} do
133
+
{v, p} -> flood(next, v, p)
134
+
end
135
+
end
136
+
137
+
def as_int(false), do: 0
138
+
def as_int(true), do: 1
139
+
end
140
+
```
141
+
142
+
<!-- livebook:{"output":true} -->
143
+
144
+
```
145
+
{:module, Garden, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:as_int, 1}}
146
+
```
147
+
148
+
```elixir
149
+
plots = Garden.plots(map)
150
+
```
151
+
152
+
<!-- livebook:{"output":true} -->
153
+
154
+
```
155
+
[
156
+
{"A", MapSet.new([{131, 11}])},
157
+
{"A",
158
+
MapSet.new([
159
+
{54, 38},
160
+
{54, 39},
161
+
{55, 38},
162
+
{56, 36},
163
+
{56, 37},
164
+
{56, 38},
165
+
{57, 37},
166
+
{57, 38},
167
+
{57, 39},
168
+
{57, 40},
169
+
{58, 36},
170
+
{58, 37},
171
+
{58, 38},
172
+
{58, 39},
173
+
{58, 40},
174
+
{59, 36},
175
+
{59, 37},
176
+
{59, 38},
177
+
{60, 36},
178
+
{60, 37},
179
+
{60, 38},
180
+
{61, 36},
181
+
{61, 37},
182
+
{61, 38},
183
+
{62, 38},
184
+
{63, 38}
185
+
])},
186
+
{"A", MapSet.new([{18, 56}])},
187
+
{"A",
188
+
MapSet.new([
189
+
{93, 86},
190
+
{94, 86},
191
+
{95, 86},
192
+
{95, 87},
193
+
{95, 88},
194
+
{96, 86},
195
+
{96, 87},
196
+
{97, 80},
197
+
{97, 81},
198
+
{97, 82},
199
+
{97, 83},
200
+
{97, 84},
201
+
{97, 85},
202
+
{97, 86},
203
+
{97, 87},
204
+
{98, 80},
205
+
{98, 81},
206
+
{98, 82},
207
+
{98, 83},
208
+
{98, 84},
209
+
{98, 85},
210
+
{99, 81},
211
+
{99, 82},
212
+
{99, 84}
213
+
])},
214
+
{"A",
215
+
MapSet.new([
216
+
{35, 102},
217
+
{42, 111},
218
+
{38, 112},
219
+
{38, 108},
220
+
{39, 111},
221
+
{35, 106},
222
+
{41, 105},
223
+
{36, 105},
224
+
{36, 108},
225
+
{42, 110},
226
+
{35, 104},
227
+
{36, 109},
228
+
{43, 111},
229
+
{42, 107},
230
+
{41, 107},
231
+
{37, 108},
232
+
{41, 111},
233
+
{42, 108},
234
+
{39, 107},
235
+
{35, 103},
236
+
{36, 111},
237
+
{37, 113},
238
+
{37, 105},
239
+
{40, 110},
240
+
{38, 107},
241
+
{43, 107},
242
+
{38, 105},
243
+
{41, 110},
244
+
{34, 108},
245
+
{37, 109},
246
+
{35, 108},
247
+
{36, 106},
248
+
{42, 109},
249
+
{38, 114},
250
+
{37, 112},
251
+
{39, 110},
252
+
{39, 109},
253
+
{36, 103},
254
+
{38, 110},
255
+
{37, 111},
256
+
{39, 108},
257
+
{38, ...},
258
+
{...},
259
+
...
260
+
])},
261
+
{"A", MapSet.new([{70, 115}, {70, 116}, {70, 117}, {71, 116}, {71, 117}, {72, 116}, {72, 117}])},
262
+
{"A",
263
+
MapSet.new([
264
+
{85, 84},
265
+
{88, 82},
266
+
{87, 83},
267
+
{83, 84},
268
+
{87, 79},
269
+
{86, 82},
270
+
{86, 84},
271
+
{83, 85},
272
+
{87, 78},
273
+
{87, 84},
274
+
{85, 79},
275
+
{87, 81},
276
+
{85, 80},
277
+
{88, 83},
278
+
{84, 84},
279
+
{86, 81},
280
+
{86, 80},
281
+
{82, 85},
282
+
{85, 82},
283
+
{82, 84},
284
+
{82, 86},
285
+
{88, 81},
286
+
{87, 82},
287
+
{86, 83},
288
+
{85, 81},
289
+
{83, 83},
290
+
{84, 80},
291
+
{88, 84},
292
+
{83, 86},
293
+
{87, 80},
294
+
{87, 77},
295
+
{81, 85},
296
+
{85, 83},
297
+
{84, 85},
298
+
{84, 82},
299
+
{84, 81},
300
+
{84, 83}
301
+
])},
302
+
{"A",
303
+
MapSet.new([
304
+
{19, 22},
305
+
{10, 25},
306
+
{16, 24},
307
+
{10, 32},
308
+
{17, 30},
309
+
{6, 29},
310
+
{18, 29},
311
+
{17, 22},
312
+
{13, 25},
313
+
{14, 24},
314
+
{10, 23},
315
+
{8, 29},
316
+
{13, 22},
317
+
{14, 28},
318
+
{6, 26},
319
+
{18, 26},
320
+
{16, 23},
321
+
{21, 26},
322
+
{19, 30},
323
+
{13, 27},
324
+
{16, 18},
325
+
{18, 23},
326
+
{9, 25},
327
+
{16, 29},
328
+
{7, 26},
329
+
{12, 27},
330
+
{16, 30},
331
+
{17, 24},
332
+
{18, 24},
333
+
{18, 22},
334
+
{6, 28},
335
+
{13, 20},
336
+
{9, 26},
337
+
{7, 27},
338
+
{11, 22},
339
+
{8, 25},
340
+
{17, 23},
341
+
{13, 23},
342
+
{20, ...},
343
+
{...},
344
+
...
345
+
])},
346
+
{"A",
347
+
MapSet.new([
348
+
{111, 103},
349
+
{107, 102},
350
+
{110, 102},
351
+
{110, 106},
352
+
{112, 103},
353
+
{114, 103},
354
+
{112, 100},
355
+
{108, 97},
356
+
{103, 96},
357
+
{109, 104},
358
+
{103, 99},
359
+
{108, 95},
360
+
{110, 104},
361
+
{113, 101},
362
+
{105, 105},
363
+
{108, 108},
364
+
{106, 105},
365
+
{111, 100},
366
+
{104, 98},
367
+
{109, 101},
368
+
{111, 104},
369
+
{107, 100},
370
+
{106, 102},
371
+
{112, 106},
372
+
{105, 95},
373
+
{104, 104},
374
+
{112, 97},
375
+
{108, 94},
376
+
{104, 97},
377
+
{111, 99},
378
+
{108, 102},
379
+
{108, 109},
380
+
{101, 97},
381
+
{104, 103},
382
+
{102, 96},
383
+
{112, 101},
384
+
{113, 97},
385
+
{100, ...},
386
+
{...},
387
+
...
388
+
])},
389
+
{"A",
390
+
MapSet.new([
391
+
{132, 99},
392
+
{136, 110},
393
+
{137, 104},
394
+
{139, 106},
395
+
{134, 98},
396
+
{139, 101},
397
+
{136, 102},
398
+
{139, 104},
399
+
{136, 96},
400
+
{134, 107},
401
+
{132, 100},
402
+
{138, 96},
403
+
{138, 102},
404
+
{135, 109},
405
+
{137, 107},
406
+
{133, 97},
407
+
{135, 107},
408
+
{137, 101},
409
+
{139, 97},
410
+
{137, 100},
411
+
{139, 109},
412
+
{135, 100},
413
+
{137, 97},
414
+
{132, 97},
415
+
{138, 105},
416
+
{137, 106},
417
+
{138, 99},
418
+
{136, 100},
419
+
{135, 98},
420
+
{139, 98},
421
+
{138, 103},
422
+
{138, 107},
423
+
{136, 108},
424
+
{139, 99},
425
+
{133, 96},
426
+
{139, 105},
427
+
{132, ...},
428
+
{...},
429
+
...
430
+
])},
431
+
{"A",
432
+
MapSet.new([
433
+
{84, 102},
434
+
{82, 100},
435
+
{86, 101},
436
+
{82, 91},
437
+
{86, 93},
438
+
{90, 93},
439
+
{88, 93},
440
+
{86, 96},
441
+
{82, 95},
442
+
{84, 93},
443
+
{85, 97},
444
+
{87, 95},
445
+
{81, 95},
446
+
{83, 100},
447
+
{87, 93},
448
+
{81, 100},
449
+
{84, 96},
450
+
{88, 95},
451
+
{81, 98},
452
+
{84, 100},
453
+
{85, 102},
454
+
{84, 91},
455
+
{82, 97},
456
+
{85, 99},
457
+
{83, 95},
458
+
{89, 96},
459
+
{88, 94},
460
+
{84, 104},
461
+
{86, 102},
462
+
{80, 92},
463
+
{89, 94},
464
+
{86, 103},
465
+
{83, 92},
466
+
{83, 96},
467
+
{82, 102},
468
+
{84, ...},
469
+
{...},
470
+
...
471
+
])},
472
+
{"A",
473
+
MapSet.new([
474
+
{65, 131},
475
+
{65, 129},
476
+
{74, 135},
477
+
{72, 134},
478
+
{71, 133},
479
+
{66, 130},
480
+
{73, 135},
481
+
{69, 130},
482
+
{74, 134},
483
+
{66, 132},
484
+
{68, 132},
485
+
{67, 128},
486
+
{69, 133},
487
+
{71, 132},
488
+
{70, 134},
489
+
{72, 132},
490
+
{72, 133},
491
+
{69, 132},
492
+
{71, 130},
493
+
{74, 136},
494
+
{73, 136},
495
+
{70, 128},
496
+
{68, 130},
497
+
{69, 129},
498
+
{73, 133},
499
+
{69, 131},
500
+
{70, 129},
501
+
{70, 130},
502
+
{67, 133},
503
+
{68, 131},
504
+
{68, 129},
505
+
{72, 135},
506
+
{68, 128},
507
+
{73, 134},
508
+
{66, ...},
509
+
{...},
510
+
...
511
+
])},
512
+
{"B", MapSet.new([{132, 12}, {132, 13}, {133, 12}, {133, 13}])},
513
+
{"B", MapSet.new([{111, 6}])},
514
+
{"B", MapSet.new([{104, 115}])},
515
+
{"B", MapSet.new([{83, 87}, {84, 87}, {84, 88}])},
516
+
{"B", MapSet.new([{83, 82}])},
517
+
{"B", MapSet.new([{71, 79}])},
518
+
{"B",
519
+
MapSet.new([
520
+
{69, 112},
521
+
{70, 109},
522
+
{70, 111},
523
+
{70, 112},
524
+
{71, 108},
525
+
{71, 109},
526
+
{71, 110},
527
+
{71, 111},
528
+
{72, 108}
529
+
])},
530
+
{"B", MapSet.new([{67, 20}, {67, 21}, {68, 19}, {68, 20}])},
531
+
{"B", MapSet.new([{63, 100}])},
532
+
{"B", MapSet.new([{44, 121}, {44, 122}])},
533
+
{"B", MapSet.new([{41, 45}])},
534
+
{"B", MapSet.new([{30, 54}])},
535
+
{"B", MapSet.new([{18, 90}])},
536
+
{"B", MapSet.new([{10, 127}])},
537
+
{"B", MapSet.new([{9, 126}])},
538
+
{"B",
539
+
MapSet.new([
540
+
{37, 75},
541
+
{39, 77},
542
+
{42, 73},
543
+
{35, 75},
544
+
{39, 81},
545
+
{40, 75},
546
+
{41, 75},
547
+
{40, 77},
548
+
{40, 81},
549
+
{40, 76},
550
+
{32, 78},
551
+
{33, 78},
552
+
{32, 77},
553
+
{37, 80},
554
+
{35, 79},
555
+
{34, 75},
556
+
{30, 78},
557
+
{39, 76},
558
+
{34, ...},
559
+
{...},
560
+
...
561
+
])},
562
+
{"B", MapSet.new([{42, 69}])},
563
+
{"B",
564
+
MapSet.new([
565
+
{0, 21},
566
+
{1, 21},
567
+
{1, 22},
568
+
{2, 21},
569
+
{2, 22},
570
+
{3, 21},
571
+
{3, 22},
572
+
{3, 23},
573
+
{3, 24},
574
+
{4, 21},
575
+
{4, 22},
576
+
{4, 23},
577
+
{4, 24},
578
+
{5, 21},
579
+
{5, 22},
580
+
{5, 23},
581
+
{5, ...},
582
+
{...},
583
+
...
584
+
])},
585
+
{"B", MapSet.new([{100, 130}])},
586
+
{"B",
587
+
MapSet.new([
588
+
{108, 25},
589
+
{108, 21},
590
+
{104, 24},
591
+
{104, 21},
592
+
{109, 18},
593
+
{107, 25},
594
+
{107, 18},
595
+
{109, 17},
596
+
{107, 27},
597
+
{106, 22},
598
+
{113, 20},
599
+
{112, 17},
600
+
{106, 26},
601
+
{108, 24},
602
+
{105, ...},
603
+
{...},
604
+
...
605
+
])},
606
+
{"B",
607
+
MapSet.new([
608
+
{15, 93},
609
+
{18, 93},
610
+
{17, 93},
611
+
{19, 97},
612
+
{13, 98},
613
+
{16, 93},
614
+
{17, 97},
615
+
{13, 95},
616
+
{14, 93},
617
+
{12, 95},
618
+
{15, 98},
619
+
{15, 96},
620
+
{14, 95},
621
+
{14, ...},
622
+
{...},
623
+
...
624
+
])},
625
+
{"B",
626
+
MapSet.new([
627
+
{45, 19},
628
+
{53, 23},
629
+
{54, 16},
630
+
{55, 17},
631
+
{53, 19},
632
+
{55, 20},
633
+
{56, 18},
634
+
{55, 21},
635
+
{49, 20},
636
+
{56, 22},
637
+
{47, 22},
638
+
{54, 23},
639
+
{47, ...},
640
+
{...},
641
+
...
642
+
])},
643
+
{"B",
644
+
MapSet.new([
645
+
{98, 9},
646
+
{97, 20},
647
+
{95, 16},
648
+
{100, 18},
649
+
{94, 21},
650
+
{97, 10},
651
+
{102, 16},
652
+
{93, 17},
653
+
{98, 19},
654
+
{95, 17},
655
+
{96, 13},
656
+
{92, ...},
657
+
{...},
658
+
...
659
+
])},
660
+
{"B",
661
+
MapSet.new([
662
+
{58, 10},
663
+
{61, 7},
664
+
{53, 9},
665
+
{58, 8},
666
+
{55, 11},
667
+
{60, 10},
668
+
{60, 11},
669
+
{60, 12},
670
+
{61, 11},
671
+
{59, 13},
672
+
{56, ...},
673
+
{...},
674
+
...
675
+
])},
676
+
{"B",
677
+
MapSet.new([
678
+
{131, 24},
679
+
{129, 25},
680
+
{130, 28},
681
+
{132, 31},
682
+
{127, 22},
683
+
{132, 33},
684
+
{130, 25},
685
+
{123, 25},
686
+
{130, 27},
687
+
{126, ...},
688
+
{...},
689
+
...
690
+
])},
691
+
{"B", MapSet.new([{30, 42}, {31, 42}, {32, 42}])},
692
+
{"C", MapSet.new([{114, 87}, {114, 88}])},
693
+
{"C", MapSet.new([{103, 27}])},
694
+
{"C", MapSet.new([{98, 4}, {98, 5}])},
695
+
{"C", MapSet.new([{92, 104}])},
696
+
{"C", MapSet.new([{83, 33}])},
697
+
{"C", MapSet.new([{82, 87}])},
698
+
{"C", MapSet.new([{76, 32}])},
699
+
{"C", MapSet.new([{75, ...}])},
700
+
{"C", MapSet.new([{...}])},
701
+
{"C", MapSet.new([...])},
702
+
{"C", ...},
703
+
{...},
704
+
...
705
+
]
706
+
```
707
+
708
+
## Part 1
709
+
710
+
```elixir
711
+
defmodule Garden.Circ do
712
+
def circumfence(set) do
713
+
{{sx, _}, {ex, _}} = Enum.min_max_by(set, &elem(&1, 0))
714
+
{{_, sy}, {_, ey}} = Enum.min_max_by(set, &elem(&1, 1))
715
+
716
+
rows = (sx - 1)..(ex + 1)//1
717
+
cols = (sy - 1)..(ey + 1)//1
718
+
719
+
vert =
720
+
rows
721
+
|> Enum.map(fn x -> count_flips(cols, &({x, &1} in set)) end)
722
+
|> Enum.sum()
723
+
724
+
hori =
725
+
cols
726
+
|> Enum.map(fn y -> count_flips(rows, &({&1, y} in set)) end)
727
+
|> Enum.sum()
728
+
729
+
vert + hori
730
+
end
731
+
732
+
defp count_flips(enum, init \\ false, func) do
733
+
Enum.reduce(enum, {0, init}, fn elem, {count, last} ->
734
+
curr = func.(elem)
735
+
{count + Garden.as_int(last != curr), curr}
736
+
end)
737
+
|> elem(0)
738
+
end
739
+
end
740
+
```
741
+
742
+
<!-- livebook:{"output":true} -->
743
+
744
+
```
745
+
{:module, Garden.Circ, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:count_flips, 3}}
746
+
```
747
+
748
+
```elixir
749
+
plots
750
+
|> Enum.map(fn {_, points} ->
751
+
Garden.Circ.circumfence(points) * MapSet.size(points)
752
+
end)
753
+
|> Enum.sum()
754
+
```
755
+
756
+
<!-- livebook:{"output":true} -->
757
+
758
+
```
759
+
1464678
760
+
```
761
+
762
+
## Part 2
763
+
764
+
```elixir
765
+
defmodule Garden.Sides do
766
+
def sides(set) do
767
+
xy = do_count(set, 0, 1)
768
+
yx = do_count(set, 1, 0)
769
+
770
+
xy + yx
771
+
end
772
+
773
+
defp do_count(set, a, b) do
774
+
set
775
+
|> Enum.group_by(&elem(&1, a), &elem(&1, b))
776
+
|> Enum.sort()
777
+
|> Enum.map(fn {_, row} -> row |> Enum.map(&(&1..&1)) |> RangeSet.new() end)
778
+
|> Enum.chunk_every(2, 1, [RangeSet.new()])
779
+
|> Enum.flat_map(fn [top, bot] ->
780
+
top.ranges
781
+
|> Enum.map(fn a..b//_ ->
782
+
Garden.as_int(not Enum.any?(bot.ranges, &(a == &1.first))) +
783
+
Garden.as_int(not Enum.any?(bot.ranges, &(b == &1.last)))
784
+
end)
785
+
end)
786
+
|> Enum.sum()
787
+
end
788
+
end
789
+
```
790
+
791
+
<!-- livebook:{"output":true} -->
792
+
793
+
```
794
+
{:module, Garden.Sides, <<70, 79, 82, 49, 0, 0, 16, ...>>, {:do_count, 3}}
795
+
```
796
+
797
+
```elixir
798
+
plots
799
+
|> Enum.map(fn {_, plot} ->
800
+
Garden.Sides.sides(plot) * MapSet.size(plot)
801
+
end)
802
+
|> Enum.sum()
803
+
```
804
+
805
+
<!-- livebook:{"output":true} -->
806
+
807
+
```
808
+
877492
809
+
```
810
+
811
+
<!-- livebook:{"offset":17848,"stamp":{"token":"XCP.d5P0-cESwFZ7qUYI4K40J_3AxksZ7WIqnIE6sn4smJvJahembJKNW-3db5gLxIgp_FEyn1pBBioGJSDsU7MO2fi1HjFgxeFNU0dLXi9Z4tf68Ey8dtld73d7SrSGlcv2DDM","version":2}} -->