Advent of Code 2024 - Day 17
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/17/input", opts).body
[a, b, c, programm] =
String.split(puzzle_input, "\n", trim: true)
|> Enum.map(fn x ->
case x do
"Register" <> <<_::binary-size(4)>> <> register ->
String.to_integer(register)
"Program: " <> programm ->
String.split(programm, ",")
|> Enum.reject(&(&1 == ","))
|> Enum.map(&String.to_integer(&1))
end
end)
state = %{a: a, b: b, c: c, output: [], programm: programm, pointer: 0}
defmodule Program do
def run(state) do
Stream.iterate(0, &(&1 + 1))
|> Enum.reduce_while(state, fn _i, state ->
%{a: a, b: b, c: c, programm: programm, pointer: pointer} = state
opcode = Enum.at(programm, pointer)
operand = Enum.at(programm, pointer + 1)
case {opcode, operand} do
{opcode, operand} when is_nil(opcode) or is_nil(operand) ->
{:halt, state}
{0, operand} ->
Map.put(state, :a, div(a, 2 ** combo(operand, state)))
|> cont()
{1, operand} ->
Map.put(state, :b, Bitwise.bxor(b, operand))
|> cont()
{2, operand} ->
Map.put(state, :b, Integer.mod(combo(operand, state), 8))
|> cont()
{3, _operand} when a == 0 ->
cont(state)
{3, operand} when a != 0 ->
cont(state, operand)
{4, _operand} ->
Map.put(state, :b, Bitwise.bxor(b, c))
|> cont()
{5, operand} ->
Map.update!(state, :output, fn o -> [Integer.mod(combo(operand, state), 8) | o] end)
|> cont()
{6, operand} ->
Map.put(state, :b, div(a, 2 ** combo(operand, state)))
|> cont()
{7, operand} ->
Map.put(state, :c, div(a, 2 ** combo(operand, state)))
|> cont()
end
end)
|> then(fn %{output: output} ->
Enum.reverse(output) |> Enum.intersperse(",") |> Enum.join()
end)
end
def combo(operand, _state) when operand in 0..3, do: operand
def combo(4, %{a: a}), do: a
def combo(5, %{b: b}), do: b
def combo(6, %{c: c}), do: c
def combo(_operand, _state), do: nil
def cont(state), do: {:cont, Map.update!(state, :pointer, &(&1 + 2))}
def cont(state, pointer), do: {:cont, Map.put(state, :pointer, pointer)}
end
Puzzle 1
puzzle_1 = fn ->
Program.run(state)
end
puzzle_1.()
Benchmarks
Benchee.run(%{
"puzzle_1" => fn -> puzzle_1.() end
})
Name |
ips |
average |
deviation |
median |
99th % |
puzzle_1 |
145.36 K |
6.88 μs |
±111.02% |
6.58 μs |
13.25 μs |