45 lines
1.1 KiB
Elixir
45 lines
1.1 KiB
Elixir
defmodule AOC.Day13 do
|
|
def parse_input do
|
|
[depart, buses] = AOC.Util.input_lines(13, 1)
|
|
depart = String.to_integer(depart)
|
|
|
|
buses =
|
|
buses
|
|
|> String.split(",")
|
|
|> Enum.map(fn
|
|
bus when bus == "x" -> :x
|
|
bus -> String.to_integer(bus)
|
|
end)
|
|
|
|
{depart, buses}
|
|
end
|
|
|
|
def find_earliest_bus(depart, buses), do: find_earliest_bus(depart, buses, {nil, :infinity})
|
|
def find_earliest_bus(_, [], earliest), do: earliest
|
|
|
|
def find_earliest_bus(depart, [bus | tl], {_, earliest} = acc) do
|
|
rounds = div(depart, bus)
|
|
rounds = if rounds * bus < depart, do: rounds + 1, else: rounds
|
|
wait = rounds * bus - depart
|
|
|
|
acc = if wait < earliest, do: {bus, wait}, else: acc
|
|
|
|
find_earliest_bus(depart, tl, acc)
|
|
end
|
|
|
|
def find_offsets(buses) do
|
|
buses
|
|
|> Enum.with_index()
|
|
|> Enum.reject(&(elem(&1, 0) |> is_atom()))
|
|
end
|
|
|
|
def parts do
|
|
{depart, buses} = parse_input()
|
|
{bus, earliest} = find_earliest_bus(depart, Enum.reject(buses, &is_atom/1))
|
|
part1 = bus * earliest
|
|
|
|
offsets = find_offsets(buses)
|
|
|
|
{part1, offsets}
|
|
end
|
|
end
|