this repo has no description
1<!-- livebook:{"persist_outputs":true} -->
2
3# Day 12
4
5```elixir
6Mix.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
26map =
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
98defmodule 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
139end
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
149plots = 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
711defmodule 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
739end
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
749plots
750|> Enum.map(fn {_, points} ->
751 Garden.Circ.circumfence(points) * MapSet.size(points)
752end)
753|> Enum.sum()
754```
755
756<!-- livebook:{"output":true} -->
757
758```
7591464678
760```
761
762## Part 2
763
764```elixir
765defmodule 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
788end
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
798plots
799|> Enum.map(fn {_, plot} ->
800 Garden.Sides.sides(plot) * MapSet.size(plot)
801end)
802|> Enum.sum()
803```
804
805<!-- livebook:{"output":true} -->
806
807```
808877492
809```
810
811<!-- livebook:{"offset":17848,"stamp":{"token":"XCP.d5P0-cESwFZ7qUYI4K40J_3AxksZ7WIqnIE6sn4smJvJahembJKNW-3db5gLxIgp_FEyn1pBBioGJSDsU7MO2fi1HjFgxeFNU0dLXi9Z4tf68Ey8dtld73d7SrSGlcv2DDM","version":2}} -->