Cleaning? Actually I'm not sure this is cleaner.
It's definitely shorter..
This commit is contained in:
parent
315162e799
commit
ebaeda4dd4
1 changed files with 17 additions and 32 deletions
|
|
@ -2,53 +2,38 @@ defmodule Day5 do
|
||||||
def run do
|
def run do
|
||||||
{rules, updates} = parseFile("data.txt")
|
{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(Enum.map(validUpdates, &middleDigit/1))}")
|
||||||
IO.puts("Part 1: #{Enum.sum(validMiddles)}")
|
|
||||||
|
|
||||||
# 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 =
|
invalidSorted =
|
||||||
Enum.map(invalidUpdates, fn update ->
|
Enum.map(invalidUpdates, fn update ->
|
||||||
Enum.sort(update, fn first, second ->
|
Enum.sort(update, &Enum.member?(rules, [&1, &2]))
|
||||||
Enum.member?(rules, [first, second])
|
|
||||||
end)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
invalidMiddles = Enum.map(invalidSorted, &middleDigit/1)
|
IO.puts("Part 2: #{Enum.sum(Enum.map(invalidSorted, &middleDigit/1))}")
|
||||||
IO.puts("Part 2: #{Enum.sum(invalidMiddles)}")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp parseFile(file) do
|
defp parseFile(file) do
|
||||||
[topSection, bottomSection] = File.read!(file) |> String.split("\n\n")
|
# 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 = String.split(topSection, "\n") |> Enum.map(fn l -> String.split(l, "|") end)
|
rules = top |> Enum.map(&String.split(&1, "|"))
|
||||||
|
updates = bottom |> Enum.drop(-1) |> Enum.map(&String.split(&1, ","))
|
||||||
updates =
|
|
||||||
String.split(bottomSection, "\n")
|
|
||||||
|> Enum.drop(-1)
|
|
||||||
|> Enum.map(fn l -> String.split(l, ",") end)
|
|
||||||
|
|
||||||
{rules, updates}
|
{rules, updates}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp updateValid?(update, rules) do
|
defp updateInvalid?(update, rules) do
|
||||||
Enum.reduce_while(rules, true, fn [left, right], acc ->
|
Enum.find(rules, false, fn [left, right] ->
|
||||||
# if it doesn't contain both, or it does and they're in the right order
|
# it is invalid if it contains both and they're in the wrong order
|
||||||
if !(Enum.member?(update, left) and Enum.member?(update, right)) or
|
Enum.member?(update, left) and Enum.member?(update, right) and
|
||||||
Enum.find_index(update, &(&1 == left)) < Enum.find_index(update, &(&1 == right)) do
|
Enum.find_index(update, &(&1 == left)) > Enum.find_index(update, &(&1 == right))
|
||||||
# continue and try the next one
|
|
||||||
{:cont, acc}
|
|
||||||
else
|
|
||||||
# otherwise halt the reduction, this update is invalid
|
|
||||||
{:halt, false}
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp middleDigit(update) do
|
defp middleDigit(l) do
|
||||||
middle = trunc(length(update) / 2)
|
middle = trunc(length(l) / 2)
|
||||||
String.to_integer(Enum.at(update, middle))
|
String.to_integer(Enum.at(l, middle))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue