You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

44 lines
1.4 KiB
Elixir

defmodule Day5 do
def run do
{rules, updates} = parseFile("data.txt")
{invalidUpdates, validUpdates} = Enum.split_with(updates, &updateInvalid?(&1, rules))
IO.puts("Part 1: #{sumMiddles(validUpdates)}")
# sort the invalid ones with a sorter that looks for [a, b] in the rules list. if [a, b] exists, sort a before b
invalidSorted =
Enum.map(invalidUpdates, fn update ->
Enum.sort(update, &Enum.member?(rules, [&1, &2]))
end)
IO.puts("Part 2: #{sumMiddles(invalidSorted)}")
end
defp parseFile(file) do
# split the file on the empty line, then map splitting on newlines on both sections
[top, bottom] = File.read!(file) |> String.split("\n\n") |> Enum.map(&String.split(&1, "\n"))
rules = top |> Enum.map(&String.split(&1, "|"))
updates = bottom |> Enum.drop(-1) |> Enum.map(&String.split(&1, ","))
{rules, updates}
end
defp updateInvalid?(update, rules) do
Enum.find(rules, false, fn [left, right] ->
# it is invalid if it contains both and they're in the wrong order
Enum.member?(update, left) and Enum.member?(update, right) and
Enum.find_index(update, &(&1 == left)) > Enum.find_index(update, &(&1 == right))
end)
end
defp sumMiddles(updates) do
Enum.map(updates, fn update ->
middle = trunc(length(update) / 2)
String.to_integer(Enum.at(update, middle))
end)
|> Enum.sum()
end
end
Day5.run()