— Day 3: Lobby —
Mix.install([{:kino_aoc, "~> 0.1"}])
Part 1
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2025", "3", System.fetch_env!("LB_AOC_SESSION_COOKIE"))
test_input = "987654321111111\n811111111111119\n234234234234278\n818181911112111"
defmodule Lobby do
def part_1(input) do
input
|> parse_input()
|> Enum.map(&max_joltage_1/1)
|> Enum.sum()
end
def parse_input(input) do
input
|> String.split()
|> Enum.map(&for(s <- String.graphemes(&1), do: String.to_integer(s)))
end
def max_joltage_1(bank) do
{_last, pop_bank} = List.pop_at(bank, -1)
max_battery = Enum.max(pop_bank)
max_battery_index = Enum.find_index(bank, &(&1 == max_battery)) + 1
submax_battery = bank |> Enum.slice(max_battery_index..-1//1) |> Enum.max()
Integer.undigits([max_battery, submax_battery])
end
def max_joltage_2(bank) do
battery_range = 11..0//-1
max_index = length(bank) - 1
bank = Enum.reverse(bank)
Enum.reduce(battery_range, {[], max_index}, fn battery_index, {joltages, max_index} ->
slice_range = battery_index..max_index
{max_joltage_index, max_joltage} = max_with_index(bank, slice_range)
{[max_joltage | joltages], max_joltage_index - 1}
end)
|> elem(0)
|> Enum.reverse()
|> Integer.undigits()
end
@spec max_with_index([integer()], Range.t()) :: {index :: integer(), max_joltage :: integer()}
defp max_with_index(bank, slice_range) do
bank
|> Enum.with_index(&{&2, &1})
|> Enum.slice(slice_range)
|> Enum.reverse()
|> Enum.max_by(&elem(&1, 1))
end
def part_2(input) do
input
|> parse_input()
|> Enum.map(&max_joltage_2/1)
|> Enum.sum()
end
end
# Lobby.part_1(test_input)
Lobby.part_1(puzzle_input)
Part 2
# Lobby.part_2(test_input)
Lobby.part_2(puzzle_input)