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()