this repo has no description
1# Day 09
2
3```elixir
4Mix.install([:kino_aoc, :image])
5```
6
7## Setup
8
9<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiI5Iiwic2Vzc2lvbl9zZWNyZXQiOiJBRFZFTlRfT0ZfQ09ERV9TRVNTSU9OIiwieWVhciI6IjIwMjUifQ","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
10
11```elixir
12{:ok, puzzle_input} =
13 KinoAOC.download_puzzle("2025", "9", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
14```
15
16```elixir
17tiles =
18 puzzle_input
19 |> String.split()
20 |> Enum.map(fn raw ->
21 raw
22 |> String.split(",")
23 |> Enum.map(&String.to_integer/1)
24 |> List.to_tuple()
25 end)
26```
27
28## Implementation
29
30```elixir
31defmodule Combinatorics do
32 def combinations2(list) do
33 Stream.unfold(list, fn
34 [] -> nil
35 [x | rest] ->
36 curr = for y <- rest, do: [x, y]
37
38 {curr, rest}
39 end)
40 |> Stream.flat_map(& &1)
41 end
42end
43```
44
45```elixir
46defmodule Rect do
47 require Record
48
49 Record.defrecordp(:rect, l: 0, t: 0, r: 0, b: 0)
50
51 def new({ax, ay}, {bx, by}) do
52 rect(l: min(ax, bx), r: max(ax, bx), t: min(ay, by), b: max(ay, by))
53 end
54
55 def area(rect() = r) do
56 width(r) * height(r)
57 end
58
59 def intersect?(
60 rect(l: al, r: ar, t: at, b: ab),
61 rect(l: bl, r: br, t: bt, b: bb)
62 ) do
63 al < br and ar > bl and at < bb and ab > bt
64 end
65
66 def width(rect(r: r, l: l)), do: r - l + 1
67 def height(rect(t: t, b: b)), do: b - t + 1
68
69 def to_svg(rect(l: x, t: y) = r, opts \\ []) do
70 ~s"""
71 <rect x="#{x}" y="#{y}" width="#{width(r)}" height="#{height(r)}"
72 #{Enum.map_join(opts, " ", fn {k, v} -> ~s(#{k}="#{v}") end)} />
73 """
74 end
75end
76```
77
78```elixir
79rects =
80 Combinatorics.combinations2(tiles)
81 |> Stream.map(fn [a, b] -> Rect.new(a, b) end)
82 |> Enum.sort()
83```
84
85<!-- livebook:{"branch_parent_index":1} -->
86
87## Part 1
88
89```elixir
90rects
91|> Enum.max_by(&Rect.area/1)
92|> IO.inspect()
93|> Rect.area()
94```
95
96<!-- livebook:{"branch_parent_index":1} -->
97
98## Part 2
99
100```elixir
101edges =
102 tiles
103 |> Enum.chunk_every(2, 1, tiles)
104 |> Enum.map(&apply(Rect, :new, &1))
105 |> Enum.sort()
106```
107
108```elixir
109# [{1916, 50285}, {94619, 50285}, {94619, 48466}, {1668, 48466}]
110# |> Stream.flat_map(fn a ->
111# for b <- tiles do
112# Rect.new(a, b)
113# end
114# end)
115rects
116|> Enum.reduce({0, nil}, fn r, {max, p} ->
117 a = Rect.area(r)
118
119 if a > max and not Enum.any?(edges, &Rect.intersect?(r, &1)) do
120 {a, r}
121 else
122 {max, p}
123 end
124end)
125```
126
127## Draw
128
129```elixir
130{{min_x, _}, {max_x, _}} = Enum.min_max(tiles)
131```
132
133```elixir
134{{_, min_y}, {_, max_y}} = Enum.min_max_by(tiles, &elem(&1, 1))
135```
136
137```elixir
138h = max_y + min_y
139w = max_x + min_x
140```
141
142```elixir
143{x, y} = hd(tiles)
144
145p1 = {:rect, 16055, 14805, 85282, 83613}
146p2 = {:rect, 5741, 50285, 94619, 67351}
147
148svg = """
149<svg xmlns="http://www.w3.org/2000/svg" width="500" viewBox="0 0 #{w} #{h}">
150 <rect width="100%" height="100%" fill="black" />
151 <path d="M#{x} #{y}#{
152 for {x, y} <- tl(tiles), do: "L#{x} #{y} "
153 } L#{x} #{y}" stroke="darkgreen" fill="green" stroke-width="200" />
154 #{Rect.to_svg(p1, stroke: :orange, fill: :transparent, "stroke-width": 200)}
155 #{Rect.to_svg(p2, stroke: :yellow, fill: :transparent, "stroke-width": 200)}
156 #{
157 for {x, y} <- tiles do
158 ~s(<rect x="#{x - 100}" y="#{y - 100}" width="200" height="200" fill="red" />)
159 end
160 }
161</svg>
162"""
163
164Kino.Image.new(svg, :svg)
165```
166
167<!-- livebook:{"offset":3329,"stamp":{"token":"XCP.SSlM8wg30CucU7IP0n8MTbPIvnvvcZRXcglo9DY17kk0O0fwtLfUUiYJauWdspkXUlp0Axl5YscQNBKK5mSycPLd0iNdz8JFPfjCg4rS2pyM3JuQj73ipXd27t8Yd0ylig","version":2}} -->