# Day 07 ```elixir Mix.install([:kino_aoc, :image]) ``` ## Parse ```elixir {:ok, puzzle_input} = KinoAOC.download_puzzle("2025", "7", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) ``` ```elixir [start | rest] = String.split(puzzle_input) start_col = byte_size(start) - byte_size(String.trim_leading(start, ".")) ``` ```elixir splitters = Enum.map(rest, fn row -> row |> String.to_charlist() |> Enum.with_index() |> Enum.filter(&(elem(&1, 0) == ?^)) |> MapSet.new(&elem(&1, 1)) end) ``` ## Part 1 ```elixir Enum.reduce(splitters, {MapSet.new([start_col]), 0}, fn splits, {beams, count} -> import MapSet, only: [intersection: 2, difference: 2, union: 2] hits = intersection(beams, splits) new_beams = for hit <- hits, dx <- [-1, 1], into: MapSet.new(), do: hit + dx beams = beams |> difference(hits) |> union(new_beams) {beams, MapSet.size(hits) + count} end) ``` ## Part 2 ```elixir Enum.reduce(splitters, %{start_col => 1}, fn splits, beams -> Enum.reduce(splits, beams, fn s, acc -> case Map.pop(acc, s) do {nil, map} -> map {count, map} -> Map.merge( map, %{ (s + 1) => count, (s - 1) => count }, fn _k, a, b -> a + b end ) end end) end) |> Enum.sum_by(&elem(&1, 1)) ``` ## Image ```elixir height = length([start | rest]) width = byte_size(start) {height, width} ``` ```elixir Image.new!(width, height) |> Image.mutate(fn img -> Image.Draw.point!(img, start_col, 0, color: :yellow) splitters |> Enum.with_index(1) |> Enum.reduce(MapSet.new([start_col]), fn {splits, y}, beams -> import MapSet, only: [intersection: 2, difference: 2, union: 2] for x <- beams do Image.Draw.point(img, x, y, color: :green) end for x <- splits do Image.Draw.point(img, x, y, color: :red) end hits = intersection(beams, splits) new_beams = for hit <- hits, dx <- [-1, 1], into: MapSet.new(), do: hit + dx beams = beams |> difference(hits) |> union(new_beams) beams end) img end) |> then(fn {:ok, img} -> img end) |> Image.resize!(5, interpolate: :nearest) ```