Day 8
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Input
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2023", "8", System.fetch_env!("LB_AOC_SESSION"))
test_input = """
RL
AAA = (BBB, CCC)
BBB = (DDD, EEE)
CCC = (ZZZ, GGG)
DDD = (DDD, DDD)
EEE = (EEE, EEE)
GGG = (GGG, GGG)
ZZZ = (ZZZ, ZZZ)
"""
"(test)"
|> String.slice(1..-2)
Part 1
defmodule Part1 do
def parse(input) do
[steps, nodes] = String.split(input, "\n\n")
network =
nodes
|> String.split("\n", trim: true)
|> Enum.map(&String.split(&1, " = "))
|> Enum.map(fn [step, coordites] ->
[left, right] = coordites |> String.slice(1..-2) |> String.split(", ")
{step, %{left: left, right: right}}
end)
|> Enum.into(%{})
{String.graphemes(steps), network}
end
def run(input) do
{steps, network} = parse(input)
Stream.cycle(steps)
|> Enum.reduce_while({"AAA", 0}, fn move, {pos, step_counter} = _acc ->
pos = walk(network, pos, move)
step_counter = step_counter + 1
if pos == "ZZZ", do: {:halt, step_counter}, else: {:cont, {pos, step_counter}}
end)
end
defp walk(network, pos, "L"), do: network[pos][:left]
defp walk(network, pos, "R"), do: network[pos][:right]
end
Part1.run(test_input)
Test Part 1
ExUnit.start(autorun: false)
defmodule PartOneTest do
use ExUnit.Case, async: true
@input puzzle_input
@expected 19783
test "part one" do
actual = Part1.run(@input)
assert actual == @expected
end
end
ExUnit.run()
Part1.run(puzzle_input)