From 9869ade6159050c8648cfe22b8edd5201c628ff3 Mon Sep 17 00:00:00 2001 From: "Ruidy (aider)" Date: Sun, 1 Dec 2024 17:59:47 +0100 Subject: [PATCH] docs: Enhance module documentation and add input validation --- lib/advent_code2024/day1.ex | 69 ++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/lib/advent_code2024/day1.ex b/lib/advent_code2024/day1.ex index 2693d0f..e8f8cfc 100644 --- a/lib/advent_code2024/day1.ex +++ b/lib/advent_code2024/day1.ex @@ -1,9 +1,30 @@ defmodule AdventCode2024.Day1 do @moduledoc """ 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 case File.read(input_file) do {:ok, content} -> @@ -16,7 +37,26 @@ defmodule AdventCode2024.Day1 do 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 case File.read(input_file) do {:ok, content} -> @@ -29,18 +69,23 @@ defmodule AdventCode2024.Day1 do end end - @spec parse_input(String.t()) :: {[integer()], [integer()]} + @spec parse_input(String.t()) :: number_pair() | {:error, String.t()} defp parse_input(content) do - {left, right} = - content - |> String.split("\n", trim: true) - |> Enum.map(&String.split(&1, ~r/\s+/, trim: true)) - |> Enum.map(fn [left, right] -> - {String.to_integer(left), String.to_integer(right)} - end) - |> Enum.unzip() + lines = String.split(content, "\n", trim: true) + + if Enum.all?(lines, &valid_line?/1) do + {left, right} = + lines + |> Enum.map(&String.split(&1, ~r/\s+/, trim: true)) + |> Enum.map(fn [left, right] -> + {String.to_integer(left), String.to_integer(right)} + end) + |> Enum.unzip() - {left, right} + {left, right} + else + {:error, "Invalid input format"} + end end @spec calculate_total_distance([integer()], [integer()]) :: integer()