Advent 2024 - Day 5
Mix.install([
{:kino, "~> 0.14.2"}
])
Setup
input = Kino.Input.textarea("Please paste your input file")
[rules, updates] = input |> Kino.Input.read() |> String.split("\n\n")
rules = rules
|> String.split("\n")
|> Enum.map(fn rule ->
rule
|> String.split("|")
|> Enum.map(&(String.to_integer(&1)))
end)
updates = updates
|> String.split("\n")
|> Enum.map(fn update ->
update
|> String.split(",")
|> Enum.map(&(String.to_integer(&1)))
end)
rule_lookup = rules
|> Enum.group_by(fn [a, _b] -> a end)
|> Enum.map(fn {k, v} ->
{k, v |> Enum.map(fn [_a, b] -> b end) |> MapSet.new()}
end)
|> Map.new()
check_valid = fn update ->
for {num, index} <- Enum.with_index(update) do
{before_updates, _after_updates} = update |> Enum.split(index)
for before_update <- before_updates do
Enum.member?(Map.get(rule_lookup, before_update, []), num)
end
end
|> List.flatten()
|> Enum.all?()
end
Part 1
for update <- updates do
is_valid = check_valid.(update)
if is_valid do
Enum.at(update, floor(length(update) / 2))
else
nil
end
end
|> Enum.filter(&(&1))
|> Enum.sum()
Part 2
for update <- updates do
is_valid = check_valid.(update)
if is_valid do
nil
else
update
|> Enum.sort(fn a, b ->
Enum.member?(Map.get(rule_lookup, a, []), b)
end)
|> Enum.at(floor(length(update) / 2))
end
end
|> Enum.filter(&(&1))
|> Enum.sum()