feat: pass the tests

This commit is contained in:
Ruidy 2024-12-05 11:10:27 +01:00
parent 901ad6c645
commit d742148e96
No known key found for this signature in database
GPG key ID: E00F51288CB857CC
3 changed files with 1476 additions and 13 deletions

View file

@ -1,4 +1,4 @@
defmodule AdventCode2024.Solutions.Day5 do defmodule AdventCode2024.Solutions.Day05 do
@moduledoc """ @moduledoc """
Day 5: Solution for Advent of Code 2024 Day 5: Solution for Advent of Code 2024
""" """
@ -38,9 +38,13 @@ defmodule AdventCode2024.Solutions.Day5 do
defp solve_content(""), do: {:error, :no_input} defp solve_content(""), do: {:error, :no_input}
defp solve_content(content) when is_binary(content) and content != "" do defp solve_content(content) when is_binary(content) and content != "" do
{rules, updates} = parse_input(content)
result = result =
content updates
|> parse_input() |> Enum.filter(&is_valid_update?(&1, rules))
|> Enum.map(&get_middle_number/1)
|> Enum.sum()
{:ok, result} {:ok, result}
end end
@ -56,7 +60,56 @@ defmodule AdventCode2024.Solutions.Day5 do
end end
defp parse_input(input) do defp parse_input(input) do
input [rules_section, updates_section] = String.split(input, "\n\n", trim: true)
rules = parse_rules(rules_section)
updates = parse_updates(updates_section)
{rules, updates}
end
defp parse_rules(rules_section) do
rules_section
|> String.split("\n", trim: true) |> String.split("\n", trim: true)
|> Enum.map(fn rule ->
[first, second] = String.split(rule, "|")
{String.to_integer(first), String.to_integer(second)}
end)
end
defp parse_updates(updates_section) do
updates_section
|> String.split("\n", trim: true)
|> Enum.map(fn update ->
update
|> String.split(",", trim: true)
|> Enum.map(&String.to_integer/1)
end)
end
defp is_valid_update?(update, rules) do
# For each pair of numbers in the update, check if they satisfy all applicable rules
update
|> Enum.with_index()
|> Enum.all?(fn {num1, idx1} ->
update
|> Enum.with_index()
|> Enum.all?(fn {num2, idx2} ->
# Only check pairs where the second number comes after the first
if idx2 > idx1 do
# Check if there's a rule requiring num2 to come before num1
not Enum.any?(rules, fn {first, second} ->
num1 == second and num2 == first
end)
else
true
end
end)
end)
end
defp get_middle_number(update) do
middle_index = div(length(update), 2)
Enum.at(update, middle_index)
end end
end end

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
defmodule AdventCode2024.Solutions.Day5Test do defmodule AdventCode2024.Solutions.Day05Test do
use ExUnit.Case use ExUnit.Case
alias AdventCode2024.Solutions.Day5 alias AdventCode2024.Solutions.Day05
@example_input """ @example_input """
47|53 47|53
@ -33,17 +33,30 @@ defmodule AdventCode2024.Solutions.Day5Test do
97,13,75,29,47 97,13,75,29,47
""" """
setup_all do
# Create a temporary file for testing
path = "test/fixtures/day05/test_input.txt"
File.mkdir_p!(Path.dirname(path))
:ok = File.write(path, @example_input)
on_exit(fn ->
File.rm!(path)
end)
{:ok, test_file: path}
end
describe "solve/1" do describe "solve/1" do
test "correctly identifies valid updates and sums middle pages" do test "correctly identifies valid updates and sums middle pages", %{test_file: path} do
assert {:ok, 143} = Day5.solve_content(@example_input) assert {:ok, 143} = Day05.solve(path)
end end
test "returns error for empty input" do test "returns error for empty input" do
assert Day5.solve("") == {:error, :no_input} assert Day05.solve("") == {:error, :no_input}
end end
test "returns error for invalid file" do test "returns error for invalid file" do
assert Day5.solve("priv/nonexistent.txt") == {:error, :enoent} assert Day05.solve("priv/nonexistent.txt") == {:error, :enoent}
end end
test "validates first update is in correct order" do test "validates first update is in correct order" do
@ -61,7 +74,11 @@ defmodule AdventCode2024.Solutions.Day5Test do
75,47,61,53,29 75,47,61,53,29
""" """
assert {:ok, 61} = Day5.solve_content(input)
path = "test/fixtures/day05/first_update.txt"
:ok = File.write(path, input)
assert {:ok, 61} = Day05.solve(path)
File.rm!(path)
end end
test "validates second update is in correct order" do test "validates second update is in correct order" do
@ -78,7 +95,11 @@ defmodule AdventCode2024.Solutions.Day5Test do
97,61,53,29,13 97,61,53,29,13
""" """
assert {:ok, 53} = Day5.solve_content(input)
path = "test/fixtures/day05/second_update.txt"
:ok = File.write(path, input)
assert {:ok, 53} = Day05.solve(path)
File.rm!(path)
end end
test "identifies invalid update due to rule violation" do test "identifies invalid update due to rule violation" do
@ -87,7 +108,11 @@ defmodule AdventCode2024.Solutions.Day5Test do
75,97,47,61,53 75,97,47,61,53
""" """
assert {:ok, 0} = Day5.solve_content(input)
path = "test/fixtures/day05/invalid_update.txt"
:ok = File.write(path, input)
assert {:ok, 0} = Day05.solve(path)
File.rm!(path)
end end
end end
end end