Advent of Code 2024 - Day 10
Mix.install([
{:req, "~> 0.5"},
{:benchee, "~> 1.3"}
])
Input
opts = [headers: [{"cookie", "session=#{System.fetch_env!("LB_AOC_SESSION")}"}]]
puzzle_input = Req.get!("https://adventofcode.com/2024/day/10/input", opts).body
defmodule Grid do
def parse(puzzle_input) do
String.split(puzzle_input, "\n", trim: true)
|> Enum.reduce({[], 0, 0}, fn row, {list, _width, height} ->
{list ++ String.graphemes(row), String.length(row), height + 1}
end)
end
def at(grid, width, height, {x, y} = pos) do
if inside?(width, height, pos), do: Enum.at(grid, y * width + x), else: nil
end
def inside?(width, height, {x, y}) do
x >= 0 and x < width and y >= 0 and y < height
end
def find_valid_paths(grid, w, h, {x, y} = pos, last_num, acc) do
cell = at(grid, w, h, pos) || ""
case Integer.parse(cell) do
{9, ""} when last_num == 8 ->
[pos | acc]
{num, ""} when num == last_num + 1 ->
[{0, -1}, {1, 0}, {0, 1}, {-1, 0}]
|> Enum.map(fn {dir_x, dir_y} -> {dir_x + x, dir_y + y} end)
|> Enum.flat_map(fn new_pos ->
find_valid_paths(grid, w, h, new_pos, num, acc)
end)
_other ->
acc
end
end
end
Puzzle 1
puzzle_1 = fn ->
{grid, w, h} = Grid.parse(puzzle_input)
coords =
for x <- 0..(w - 1), y <- 0..(h - 1) do
{x, y}
end
Enum.flat_map(coords, fn pos ->
case Grid.at(grid, w, h, pos) do
"0" -> Grid.find_valid_paths(grid, w, h, pos, -1, []) |> Enum.uniq()
_other -> []
end
end)
|> Enum.count()
end
puzzle_1.()
Puzzle 2
puzzle_2 = fn ->
{grid, w, h} = Grid.parse(puzzle_input)
coords =
for x <- 0..(w - 1), y <- 0..(h - 1) do
{x, y}
end
Enum.flat_map(coords, fn pos ->
case Grid.at(grid, w, h, pos) do
"0" -> Grid.find_valid_paths(grid, w, h, pos, -1, [])
_other -> []
end
end)
|> Enum.count()
end
puzzle_2.()
Benchmarks
Benchee.run(
%{
"puzzle_1" => fn -> puzzle_1.() end,
"puzzle_2" => fn -> puzzle_2.() end
})
Name |
ips |
average |
deviation |
median |
99th % |
puzzle_2 |
29.75 |
33.62 ms |
±8.61% |
33.33 ms |
53.41 ms |
puzzle_1 |
29.69 |
33.68 ms |
±6.49% |
33.36 ms |
50.11 ms |