# Day 09 ```elixir Mix.install([:kino_aoc, :image]) ``` ## Setup ```elixir {:ok, puzzle_input} = KinoAOC.download_puzzle("2025", "9", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) ``` ```elixir tiles = puzzle_input |> String.split() |> Enum.map(fn raw -> raw |> String.split(",") |> Enum.map(&String.to_integer/1) |> List.to_tuple() end) ``` ## Implementation ```elixir defmodule Combinatorics do def combinations2(list) do Stream.unfold(list, fn [] -> nil [x | rest] -> curr = for y <- rest, do: [x, y] {curr, rest} end) |> Stream.flat_map(& &1) end end ``` ```elixir defmodule Rect do require Record Record.defrecordp(:rect, l: 0, t: 0, r: 0, b: 0) def new({ax, ay}, {bx, by}) do rect(l: min(ax, bx), r: max(ax, bx), t: min(ay, by), b: max(ay, by)) end def area(rect() = r) do width(r) * height(r) end def intersect?( rect(l: al, r: ar, t: at, b: ab), rect(l: bl, r: br, t: bt, b: bb) ) do al < br and ar > bl and at < bb and ab > bt end def width(rect(r: r, l: l)), do: r - l + 1 def height(rect(t: t, b: b)), do: b - t + 1 def to_svg(rect(l: x, t: y) = r, opts \\ []) do ~s""" ~s(#{k}="#{v}") end)} /> """ end end ``` ```elixir rects = Combinatorics.combinations2(tiles) |> Stream.map(fn [a, b] -> Rect.new(a, b) end) |> Enum.sort() ``` ## Part 1 ```elixir rects |> Enum.max_by(&Rect.area/1) |> IO.inspect() |> Rect.area() ``` ## Part 2 ```elixir edges = tiles |> Enum.chunk_every(2, 1, tiles) |> Enum.map(&apply(Rect, :new, &1)) |> Enum.sort() ``` ```elixir # [{1916, 50285}, {94619, 50285}, {94619, 48466}, {1668, 48466}] # |> Stream.flat_map(fn a -> # for b <- tiles do # Rect.new(a, b) # end # end) rects |> Enum.reduce({0, nil}, fn r, {max, p} -> a = Rect.area(r) if a > max and not Enum.any?(edges, &Rect.intersect?(r, &1)) do {a, r} else {max, p} end end) ``` ## Draw ```elixir {{min_x, _}, {max_x, _}} = Enum.min_max(tiles) ``` ```elixir {{_, min_y}, {_, max_y}} = Enum.min_max_by(tiles, &elem(&1, 1)) ``` ```elixir h = max_y + min_y w = max_x + min_x ``` ```elixir {x, y} = hd(tiles) p1 = {:rect, 16055, 14805, 85282, 83613} p2 = {:rect, 5741, 50285, 94619, 67351} svg = """ #{Rect.to_svg(p1, stroke: :orange, fill: :transparent, "stroke-width": 200)} #{Rect.to_svg(p2, stroke: :yellow, fill: :transparent, "stroke-width": 200)} #{ for {x, y} <- tiles do ~s() end } """ Kino.Image.new(svg, :svg) ```