Day 7
Mix.install([
{:kino_aoc, github: "troynt/kino_aoc", branch: "main" }
])
Setup
{:ok, input} = KinoAOC.download_puzzle("2025", "7", System.fetch_env!("LB_AOC_SESSION"))
{:ok,
"......................................................................S......................................................................\n.............................................................................................................................................\n......................................................................^......................................................................\n.............................................................................................................................................\n.....................................................................^.^.....................................................................\n.............................................................................................................................................\n....................................................................^.^.^....................................................................\n.............................................................................................................................................\n...................................................................^.^...^...................................................................\n.............................................................................................................................................\n..................................................................^.^...^.^..................................................................\n.............................................................................................................................................\n.................................................................^.^.^.^...^.................................................................\n.............................................................................................................................................\n................................................................^...^...^...^................................................................\n.............................................................................................................................................\n...............................................................^.^.^.^.^.....^...............................................................\n.............................................................................................................................................\n..............................................................^.^.^.^...^.^.^.^..............................................................\n.............................................................................................................................................\n.............................................................^.^.^.^.^.^.^.^...^.............................................................\n.............................................................................................................................................\n............................................................^...^.^.^.^...^.....^............................................................\n.............................................................................................................................................\n...........................................................^...^.^.^.^.^.^.....^.^...........................................................\n.............................................................................................................................................\n..........................................................^.^.^.^.^.^.^.^.^.....^.^..........................................................\n.............................................................................................................................................\n.........................................................^.^.^.^.....^.^...^.^.^...^...................................." <> ...}
Disclaimer!
This code is terrible. Part 2 was tricky due to spacing inconsistencies between my copy & pasted example and downloaded input. Will need to revisit when I have time to investigate. The solution should be simpler.
ex = """
.......S.......
...............
.......^.......
...............
......^.^......
...............
.....^.^.^.....
...............
....^.^...^....
...............
...^.^...^.^...
...............
..^...^.....^..
...............
.^.^.^.^.^...^.
...............
"""
".......S.......\n...............\n.......^.......\n...............\n......^.^......\n...............\n.....^.^.^.....\n...............\n....^.^...^....\n...............\n...^.^...^.^...\n...............\n..^...^.....^..\n...............\n.^.^.^.^.^...^.\n...............\n"
Solution
defmodule Day7 do
@doc """
iex> Day7.parse("..S..") |> elem(1)
{2, 0}
"""
def parse(str) do
String.split(str)
|> Enum.with_index()
|> Enum.flat_map(fn {row, y} ->
String.split(row, "", trim: true)
|> Enum.with_index()
|> Enum.map(fn {v, x} ->
{v, {x, y}}
end)
end)
|> Enum.reduce({%{}, nil }, fn {v, pos}, {map, start} -> # acc is grid, start, beam positions
start = if v == "S" do
pos
else
start
end
{ Map.put(map, pos, {v, pos}), start }
end)
end
def add_vector({x, y}, {dx, dy}) do
{ x + dx, y + dy }
end
@doc """
iex> Day7.put_beam(%{{0,0} => 1}, {0,0})
%{{0, 0} => {"|", {0, 0}}}
"""
def put_beam(grid, pos) do
if Map.has_key?(grid, pos) do
Map.put(grid, pos, {"|", pos})
else
grid
end
end
def handle_beams(grid, active_beams), do: handle_beams(grid, active_beams, 0)
@doc """
iex> Day7.handle_beams(%{{0,0} => 1}, [], 0)
{%{{0, 0} => 1}, 0}
"""
def handle_beams(grid, [], split_count), do: { grid, split_count }
def handle_beams(grid, [pos], split_count), do: handle_beam(grid, pos, split_count)
def handle_beams(grid, [pos | rest], split_count) do
# print(grid)
{grid, split_count } = handle_beam(grid, pos, split_count)
handle_beams(grid, rest, split_count)
end
def handle_space(grid, p, split_count) do
if Map.has_key?(grid, p) do
handle_beam(put_beam(grid, p), p, split_count)
else
handle_beams(grid, [], split_count)
end
end
def handle_split(grid, split_pos, split_count) do
a = add_vector(split_pos, {-1, 0})
b = add_vector(split_pos, {1, 0})
to_add = [a, b] |> Enum.filter(fn p -> Map.has_key?(grid, p) end)
grid = grid
|> put_beam(a)
|> put_beam(b)
if length(to_add) > 0 do
handle_beams(grid, [a, b], split_count + 1)
else
handle_beams(grid, [], split_count)
end
end
def handle_beam(grid, beam_source, split_count) do
if Map.has_key?(grid, beam_source) do
new_pos = add_vector(beam_source, {0, 1})
case Map.get(grid, new_pos, nil) do
{"^", p } -> handle_split(grid, p, split_count)
{".", p } -> handle_space(grid, p, split_count)
{"|", _ } -> { grid, split_count }
nil -> { grid, split_count }
end
else
{ grid, split_count }
end
end
def print(grid) do
{max_x, _} = grid |> Map.keys() |> Enum.max_by(fn {x, _} -> x end)
{_, max_y} = grid |> Map.keys() |> Enum.max_by(fn {_, y} -> y end)
for y <- 0..max_y do
for x <- 0..max_x do
{v, _pos } = Map.get(grid, {x, y}, {".", {x, y}})
IO.write(v)
end
IO.puts("")
end
IO.puts("")
end
def solve(str) do
{grid, start_pos} = parse(str)
{ _, split_count } = handle_beams(grid, [start_pos])
split_count
end
end
{:module, Day7, <<70, 79, 82, 49, 0, 0, 32, ...>>, ...}
Part 1
Day7.solve(input)
1573