aoc/2022/lib/days/day16.ex
2023-04-17 20:18:20 +02:00

81 lines
1.9 KiB
Elixir

defmodule AOC.Day16 do
use AOC.Day, day: 16, debug: true, input: "example"
alias AOC.Day16.{ValveRegistry, Valve}
defmodule Valve do
use GenServer
@impl true
def init(state) do
state = Map.put(state, :released, 0)
state = Map.put(state, :open?, false)
{:ok, state}
end
def get_rate(valve) do
GenServer.call(valve, :get_rate)
end
def tick(valve) do
GenServer.call(valve, :tick)
end
def open(valve) do
GenServer.call(valve, :open)
end
@impl true
def handle_call(:get_rate, _from, %{rate: rate} = state) do
{:reply, rate, state}
end
def handle_call(:tick, _from, %{open?: open?, released: released, rate: rate} = state) do
released = if open?, do: released + rate, else: released
{:reply, :ok, %{state | released: released}}
end
def handle_call(:open, _from, state) do
{:reply, :ok, %{state | open?: true}}
end
end
@line_regex ~r/Valve (?<name>[A-Z]{2}) has flow rate=(?<rate>\d+); tunnels? leads? to valves? (?<tunnels>.*)/
def parse_input(lines) do
{:ok, _} = Registry.start_link(keys: :unique, name: ValveRegistry)
lines
|> Enum.map(fn line ->
%{"name" => name, "rate" => rate, "tunnels" => tunnels} =
Regex.named_captures(@line_regex, line)
%{name: name, rate: String.to_integer(rate), tunnels: String.split(tunnels, ", ")}
end)
|> Enum.into(%{}, fn %{name: name} = valve ->
{:ok, pid} =
GenServer.start_link(Valve, valve, name: {:via, Registry, {ValveRegistry, name}})
{name, pid}
end)
end
def part1(valves) do
Enum.map(valves, fn {name, valve} ->
rate = Valve.get_rate(valve)
{name, rate}
end)
|> Enum.sort_by(&elem(&1, 1), :desc)
|> IO.inspect()
:ok
end
def tick(valves) do
Enum.each(valves, fn {_, valve} ->
Valve.tick(valve)
end)
end
def part2(_input) do
end
end