this repo has no description
at master 3.5 kB view raw
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}} -->