— Day 1: Secret Entrance —
Mix.install([{:kino_aoc, "~> 0.1"}])
Part 1
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2025", "1", System.fetch_env!("LB_AOC_SESSION_COOKIE"))
defmodule SecretEntrance do
@starting_pos 50
@dial_range 0..99
@dial_max Enum.max(@dial_range)
@dial_min Enum.min(@dial_range)
@dial_size Range.size(@dial_range)
def part_1(input) do
input
|> String.split()
|> Enum.map(&parse_clicks/1)
|> Enum.reduce([@starting_pos], &map_positions_1/2)
|> Enum.sum_by(&add_zero/1)
end
defp parse_clicks("L" <> clicks), do: {"L", String.to_integer(clicks)}
defp parse_clicks("R" <> clicks), do: {"R", String.to_integer(clicks)}
defp map_positions_1({dir, clicks}, [current_pos | _rest] = positions) do
clicks = rem(clicks, @dial_size)
new_position = dir |> turn_dial(current_pos, clicks) |> new_position()
[new_position | positions]
end
defp turn_dial("L", current_pos, clicks), do: current_pos - clicks
defp turn_dial("R", current_pos, clicks), do: current_pos + clicks
defp new_position(turn) when turn < @dial_min, do: @dial_size + turn
defp new_position(turn) when turn > @dial_max, do: abs(@dial_size - turn)
defp new_position(turn), do: turn
defp add_zero(0), do: 1
defp add_zero(_), do: 0
def part_2(input) do
input
|> String.split()
|> Enum.map(&parse_clicks/1)
|> Enum.reduce([@starting_pos], &map_positions_2/2)
|> Enum.sum_by(&add_zero/1)
end
defp map_positions_2({dir, clicks}, [current_pos | rest]) when clicks > @dial_max do
zeros = List.duplicate(0, div(clicks, @dial_size))
clicks = rem(clicks, @dial_size)
positions = [current_pos | zeros] ++ rest
map_positions_2({dir, clicks}, positions)
end
defp map_positions_2({dir, clicks}, [current_pos | _rest] = positions) do
clicks = rem(clicks, @dial_size)
turn = turn_dial(dir, current_pos, clicks)
new_position = new_position(turn)
if turn not in @dial_range and 0 not in [new_position, current_pos] do
[new_position, 0] ++ positions
else
[new_position | positions]
end
end
end
test_input = "L68\nL30\nR48\nL5\nR60\nL55\nL1\nL99\nR14\nL82"
SecretEntrance.part_1(puzzle_input)
Part 2
# SecretEntrance.part_2(test_input)
SecretEntrance.part_2(puzzle_input)