# Advent of Code 2024 - Day 10
```elixir
Mix.install([
{:kino_aoc, "~> 0.1.7"}
])
```
## Introduction
[2024 - Day 10](https://adventofcode.com/2024/day/10)
## Puzzle
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxMCIsInNlc3Npb25fc2VjcmV0IjoiQU9DX1NFU1NJT04iLCJ5ZWFyIjoiMjAyNCJ9","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
```elixir
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2024", "10", System.fetch_env!("LB_AOC_SESSION"))
```
## Parser
### Code - Parser
```elixir
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
```elixir
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
```elixir
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
```
<!-- livebook:{"branch_parent_index":2} -->
## Part One
### Code - Part 1
```elixir
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
```elixir
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
```elixir
PartOne.solve(puzzle_input)
```
<!-- livebook:{"branch_parent_index":2} -->
## Part Two
### Code - Part 2
```elixir
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
```elixir
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
```elixir
PartTwo.solve(puzzle_input)
```
<!-- livebook:{"offset":3593,"stamp":{"token":"XCP.9_eleOGY4ns2OmLDh_iv1pYZaP4hIcQ8sN6aXhFBlJw7fe7FzNjCxX-z3NWzn9wlnrMoiNUnvti1leIOm4nZ2rwDOX3zv7nNlROwtrZZaUFgFpgP-Ro","version":2}} -->