diff --git a/day5/main.exs b/day5/main.exs index 755da4d..0ee8ea1 100644 --- a/day5/main.exs +++ b/day5/main.exs @@ -2,53 +2,38 @@ defmodule Day5 do def run do {rules, updates} = parseFile("data.txt") - {validUpdates, invalidUpdates} = Enum.split_with(updates, &updateValid?(&1, rules)) + {invalidUpdates, validUpdates} = Enum.split_with(updates, &updateInvalid?(&1, rules)) - validMiddles = Enum.map(validUpdates, &middleDigit/1) - IO.puts("Part 1: #{Enum.sum(validMiddles)}") + IO.puts("Part 1: #{Enum.sum(Enum.map(validUpdates, &middleDigit/1))}") - # sort the invalid ones with a custom sorter that looks for [a, b] in the rules list. if [a, b] exists, sort a before b + # 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, fn first, second -> - Enum.member?(rules, [first, second]) - end) + Enum.sort(update, &Enum.member?(rules, [&1, &2])) end) - invalidMiddles = Enum.map(invalidSorted, &middleDigit/1) - IO.puts("Part 2: #{Enum.sum(invalidMiddles)}") + IO.puts("Part 2: #{Enum.sum(Enum.map(invalidSorted, &middleDigit/1))}") end defp parseFile(file) do - [topSection, bottomSection] = File.read!(file) |> String.split("\n\n") - - rules = String.split(topSection, "\n") |> Enum.map(fn l -> String.split(l, "|") end) - - updates = - String.split(bottomSection, "\n") - |> Enum.drop(-1) - |> Enum.map(fn l -> String.split(l, ",") end) - + # split the file by the empty line, then map splitting by 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 updateValid?(update, rules) do - Enum.reduce_while(rules, true, fn [left, right], acc -> - # if it doesn't contain both, or it does and they're in the right order - if !(Enum.member?(update, left) and Enum.member?(update, right)) or - Enum.find_index(update, &(&1 == left)) < Enum.find_index(update, &(&1 == right)) do - # continue and try the next one - {:cont, acc} - else - # otherwise halt the reduction, this update is invalid - {:halt, false} - 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 middleDigit(update) do - middle = trunc(length(update) / 2) - String.to_integer(Enum.at(update, middle)) + defp middleDigit(l) do + middle = trunc(length(l) / 2) + String.to_integer(Enum.at(l, middle)) end end