docs: Enhance module documentation and add input validation

This commit is contained in:
Ruidy (aider) 2024-12-01 17:59:47 +01:00
parent 5a966b4839
commit 9869ade615
No known key found for this signature in database
GPG key ID: E00F51288CB857CC

View file

@ -1,9 +1,30 @@
defmodule AdventCode2024.Day1 do defmodule AdventCode2024.Day1 do
@moduledoc """ @moduledoc """
Solution for Advent of Code 2024 - Day 1: Historian Hysteria Solution for Advent of Code 2024 - Day 1: Historian Hysteria
This module processes pairs of numbers from an input file to:
- Calculate total distance between paired numbers (Part 1)
- Calculate similarity scores based on frequency matching (Part 2)
Input file format expects lines with two space-separated integers.
""" """
@spec solve(String.t()) :: {:ok, integer()} | {:error, String.t()} @type result :: {:ok, integer()} | {:error, String.t()}
@type number_pair :: {[integer()], [integer()]}
@doc """
Solves Part 1 of Day 1 challenge.
Takes an input file path and calculates the total distance between paired numbers.
## Parameters
- input_file: Path to input file (defaults to "day1/input.txt")
## Returns
- `{:ok, result}` where result is the calculated total distance
- `{:error, reason}` if file reading fails
"""
@spec solve(String.t()) :: result()
def solve(input_file \\ "day1/input.txt") do def solve(input_file \\ "day1/input.txt") do
case File.read(input_file) do case File.read(input_file) do
{:ok, content} -> {:ok, content} ->
@ -16,7 +37,26 @@ defmodule AdventCode2024.Day1 do
end end
end end
@spec solve_part2(String.t()) :: {:ok, integer()} | {:error, String.t()} defp valid_line?(line) do
case String.split(line, ~r/\s+/, trim: true) do
[left, right] -> match?({:ok, _}, Integer.parse(left)) && match?({:ok, _}, Integer.parse(right))
_ -> false
end
end
@doc """
Solves Part 2 of Day 1 challenge.
Takes an input file path and calculates similarity scores based on number frequencies.
## Parameters
- input_file: Path to input file (defaults to "day1/input.txt")
## Returns
- `{:ok, result}` where result is the similarity score
- `{:error, reason}` if file reading fails
"""
@spec solve_part2(String.t()) :: result()
def solve_part2(input_file \\ "day1/input.txt") do def solve_part2(input_file \\ "day1/input.txt") do
case File.read(input_file) do case File.read(input_file) do
{:ok, content} -> {:ok, content} ->
@ -29,18 +69,23 @@ defmodule AdventCode2024.Day1 do
end end
end end
@spec parse_input(String.t()) :: {[integer()], [integer()]} @spec parse_input(String.t()) :: number_pair() | {:error, String.t()}
defp parse_input(content) do defp parse_input(content) do
{left, right} = lines = String.split(content, "\n", trim: true)
content
|> String.split("\n", trim: true) if Enum.all?(lines, &valid_line?/1) do
|> Enum.map(&String.split(&1, ~r/\s+/, trim: true)) {left, right} =
|> Enum.map(fn [left, right] -> lines
{String.to_integer(left), String.to_integer(right)} |> Enum.map(&String.split(&1, ~r/\s+/, trim: true))
end) |> Enum.map(fn [left, right] ->
|> Enum.unzip() {String.to_integer(left), String.to_integer(right)}
end)
|> Enum.unzip()
{left, right} {left, right}
else
{:error, "Invalid input format"}
end
end end
@spec calculate_total_distance([integer()], [integer()]) :: integer() @spec calculate_total_distance([integer()], [integer()]) :: integer()