feat: pass examples for part2

This commit is contained in:
Ruidy 2024-12-05 11:59:23 +01:00
parent fbc39fe430
commit e6c0d59c2b
No known key found for this signature in database
GPG key ID: E00F51288CB857CC
2 changed files with 60 additions and 78 deletions

View file

@ -5,71 +5,61 @@ defmodule AdventCode2024.Solutions.Day05 do
@behaviour AdventCode2024.Solution @behaviour AdventCode2024.Solution
@default_input "priv/inputs/day05/input.txt" @impl true
@doc """
Solve part 1 of the challenge
"""
def solve(input_file \\ @default_input)
def solve(""), do: {:error, :no_input} def solve(""), do: {:error, :no_input}
def solve(input_file) when is_binary(input_file) and input_file != "" do def solve(path \\ "priv/inputs/day05/input.txt") do
case File.read(input_file) do case File.read(path) do
{:ok, content} -> solve_content(content) {:ok, content} -> solve_content(content)
{:error, reason} -> {:error, reason} {:error, :enoent} -> {:error, :enoent}
_ -> {:error, :no_input}
end end
end end
@doc """ def solve_content(""), do: {:error, :no_input}
Solve part 2 of the challenge
""" def solve_content(content) do
def solve_part2(input_file \\ @default_input) {rules, updates} = parse_input(content)
valid_updates = Enum.filter(updates, &is_valid_update?(&1, rules))
sum = valid_updates |> Enum.map(&get_middle_number/1) |> Enum.sum()
{:ok, sum}
end
@impl true
def solve_part2(""), do: {:error, :no_input} def solve_part2(""), do: {:error, :no_input}
def solve_part2(input_file) when is_binary(input_file) and input_file != "" do def solve_part2(path \\ "priv/inputs/day05/input.txt") do
case File.read(input_file) do case File.read(path) do
{:ok, content} -> solve_part2_content(content) {:ok, content} -> solve_part2_content(content)
{:error, reason} -> {:error, reason} {:error, :enoent} -> {:error, :enoent}
_ -> {:error, :no_input}
end end
end end
# Private functions def solve_part2_content(""), do: {:error, :no_input}
defp solve_content(""), do: {:error, :no_input} def solve_part2_content(content) do
defp solve_content(content) when is_binary(content) and content != "" do
{rules, updates} = parse_input(content) {rules, updates} = parse_input(content)
invalid_updates = Enum.reject(updates, &is_valid_update?(&1, rules))
result = sum =
updates invalid_updates
|> Enum.filter(&is_valid_update?(&1, rules)) |> Enum.map(&order_update(&1, rules))
|> Enum.map(&get_middle_number/1) |> Enum.map(&get_middle_number/1)
|> Enum.sum() |> Enum.sum()
{:ok, result} {:ok, sum}
end end
defp solve_part2_content(""), do: {:error, :no_input} defp parse_input(content) do
[rules_str, updates_str] = String.split(content, "\n\n", trim: true)
defp solve_part2_content(content) when is_binary(content) and content != "" do rules = parse_rules(rules_str)
result = updates = parse_updates(updates_str)
content
|> parse_input()
{:ok, result}
end
defp parse_input(input) do
[rules_section, updates_section] = String.split(input, "\n\n", trim: true)
rules = parse_rules(rules_section)
updates = parse_updates(updates_section)
{rules, updates} {rules, updates}
end end
defp parse_rules(rules_section) do defp parse_rules(rules_str) do
rules_section rules_str
|> String.split("\n", trim: true) |> String.split("\n", trim: true)
|> Enum.map(fn rule -> |> Enum.map(fn rule ->
[first, second] = String.split(rule, "|") [first, second] = String.split(rule, "|")
@ -77,39 +67,43 @@ defmodule AdventCode2024.Solutions.Day05 do
end) end)
end end
defp parse_updates(updates_section) do defp parse_updates(updates_str) do
updates_section updates_str
|> String.split("\n", trim: true) |> String.split("\n", trim: true)
|> Enum.map(fn update -> |> Enum.map(fn line ->
update line
|> String.split(",", trim: true) |> String.split(",")
|> Enum.map(&String.to_integer/1) |> Enum.map(&String.to_integer/1)
end) end)
end end
defp is_valid_update?(update, rules) do defp is_valid_update?(update, rules) do
# For each pair of numbers in the update, check if they satisfy all applicable rules
update update
|> Enum.with_index() |> Enum.chunk_every(2, 1, :discard)
|> Enum.all?(fn {num1, idx1} -> |> Enum.all?(fn [a, b] -> is_valid_order?(a, b, rules) end)
update end
|> Enum.with_index()
|> Enum.all?(fn {num2, idx2} -> defp is_valid_order?(a, b, rules) do
# Only check pairs where the second number comes after the first not Enum.any?(rules, fn {x, y} -> x == b and y == a end)
if idx2 > idx1 do end
# Check if there's a rule requiring num2 to come before num1
not Enum.any?(rules, fn {first, second} -> defp get_middle_number(list) do
num1 == second and num2 == first middle_index = div(length(list), 2)
end) Enum.at(list, middle_index)
else end
true
end defp order_update(update, rules) do
end) update
|> Enum.sort(fn a, b ->
case {should_come_before?(a, b, rules), should_come_before?(b, a, rules)} do
{true, false} -> true
{false, true} -> false
_ -> a > b
end
end) end)
end end
defp get_middle_number(update) do defp should_come_before?(a, b, rules) do
middle_index = div(length(update), 2) Enum.any?(rules, fn {x, y} -> x == a and y == b end)
Enum.at(update, middle_index)
end end
end end

View file

@ -1,12 +0,0 @@
97|13
97|61
97|53
97|29
61|13
61|53
61|29
53|29
29|13
97,61,53,29,13
61,53,29,13