Advent of Code 2024 - Day 10
Mix.install([
{:kino_aoc, "~> 0.1.7"}
])
Introduction
2024 - Day 10
Puzzle
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2024", "10", System.fetch_env!("LB_AOC_SESSION"))
Parser
Code - Parser
defmodule Parser do
def parse(input) do
input
|> String.split("\n", trim: true)
|> Enum.with_index()
|> Enum.reduce([], fn {line, y}, map ->
line
|> String.graphemes()
|> Enum.with_index()
|> Enum.reduce(map, fn {char, x}, map ->
[{{x, y}, String.to_integer(char)} | map]
end)
end)
|> Map.new()
end
end
Tests - Parser
ExUnit.start(autorun: false)
defmodule ParserTest do
use ExUnit.Case, async: true
import Parser
@input """
01
23
"""
@expected %{{0, 0} => 0, {0, 1} => 2, {1, 0} => 1, {1, 1} => 3}
test "parse test" do
actual = parse(@input)
assert actual == @expected
end
end
ExUnit.run()
Shared
defmodule Shared do
@dir [{1, 0}, {0, -1}, {-1, 0}, {0, 1}]
def hike(map, curr = {x, y}) do
case Map.get(map, curr) do
9 ->
curr
height ->
@dir
|> Enum.map(fn {dx, dy} -> {x + dx, y + dy} end)
|> Enum.filter(fn next ->
case Map.get(map, next) do
nil -> false
next_height when next_height - height != 1 -> false
_ -> true
end
end)
|> Enum.map(fn next -> hike(map, next) end)
end
end
end
Part One
Code - Part 1
defmodule PartOne do
import Shared
def solve(input) do
IO.puts("--- Part One ---")
IO.puts("Result: #{run(input)}")
end
def run(input) do
map = Parser.parse(input)
map
|> Enum.filter(fn {_, v} -> v == 0 end)
|> Enum.map(fn {start, _} ->
hike(map, start)
|> List.flatten()
|> Enum.uniq()
|> Enum.count()
end)
|> Enum.sum()
end
end
Tests - Part 1
ExUnit.start(autorun: false)
defmodule PartOneTest do
use ExUnit.Case, async: true
import PartOne
@input """
89010123
78121874
87430965
96549874
45678903
32019012
01329801
10456732
"""
@expected 36
test "part one" do
actual = run(@input)
assert actual == @expected
end
end
ExUnit.run()
Solution - Part 1
PartOne.solve(puzzle_input)
Part Two
Code - Part 2
defmodule PartTwo do
import Shared
def solve(input) do
IO.puts("--- Part Two ---")
IO.puts("Result: #{run(input)}")
end
def run(input) do
map = Parser.parse(input)
map
|> Enum.filter(fn {_, v} -> v == 0 end)
|> Enum.map(fn {start, _} -> hike(map, start) end)
|> List.flatten()
|> Enum.count()
end
end
Tests - Part 2
ExUnit.start(autorun: false)
defmodule PartTwoTest do
use ExUnit.Case, async: true
import PartTwo
@input """
89010123
78121874
87430965
96549874
45678903
32019012
01329801
10456732
"""
@expected 81
test "part two" do
actual = run(@input)
assert actual == @expected
end
end
ExUnit.run()
Solution - Part 2
PartTwo.solve(puzzle_input)