feat: read input from file

This commit is contained in:
Ruidy 2024-12-04 18:06:49 +01:00
parent 143b8c0742
commit 04787bd7f9
No known key found for this signature in database
GPG key ID: E00F51288CB857CC
2 changed files with 45 additions and 22 deletions

View file

@ -82,7 +82,12 @@ defmodule AdventCode2024.Solutions.Day04 do
|> count_word_occurrences("XMAS") |> count_word_occurrences("XMAS")
end end
def solve_part2(_input_file) do def solve_part2(input_file \\ @default_input) do
input_file
|> File.stream!()
|> Stream.map(&String.trim/1)
|> Enum.to_list()
|> count_x_mas()
end end
def count_x_mas(grid) do def count_x_mas(grid) do
@ -94,7 +99,8 @@ defmodule AdventCode2024.Solutions.Day04 do
row row
|> Enum.with_index() |> Enum.with_index()
|> Enum.reduce(acc, fn {cell, col_idx}, acc_inner -> |> Enum.reduce(acc, fn {cell, col_idx}, acc_inner ->
if cell == "A" do # Start from the center A # Start from the center A
if cell == "A" do
acc_inner + check_x_patterns(processed_grid, {row_idx, col_idx}) acc_inner + check_x_patterns(processed_grid, {row_idx, col_idx})
else else
acc_inner acc_inner
@ -116,28 +122,45 @@ defmodule AdventCode2024.Solutions.Day04 do
end end
defp check_x_pattern(grid, {row, col}, step) do defp check_x_pattern(grid, {row, col}, step) do
# Check if we can form an X pattern with MAS on both diagonals # For a valid X pattern, we need:
check_diagonal(grid, {row, col}, {-step, -step}, {step, step}) and # top-left to bottom-right # 1. Both diagonals must have valid MAS patterns
check_diagonal(grid, {row, col}, {-step, step}, {step, -step}) # top-right to bottom-left # 2. The patterns must not share any positions except the center A
# 3. Both diagonals must be the same length (step)
top_left = {row - step, col - step}
top_right = {row - step, col + step}
bottom_left = {row + step, col - step}
bottom_right = {row + step, col + step}
# Check if all positions are within bounds
# Check both diagonals
# First diagonal: top-left to bottom-right
# First diagonal: bottom-right to top-left (reverse)
# Second diagonal: top-right to bottom-left
# Second diagonal: bottom-left to top-right (reverse)
within_bounds?(grid, row - step, col - step) and
within_bounds?(grid, row - step, col + step) and
within_bounds?(grid, row + step, col - step) and
within_bounds?(grid, row + step, col + step) and
(check_diagonal_pattern(grid, top_left, bottom_right, {row, col}) or
check_diagonal_pattern(grid, bottom_right, top_left, {row, col})) and
(check_diagonal_pattern(grid, top_right, bottom_left, {row, col}) or
check_diagonal_pattern(grid, bottom_left, top_right, {row, col}))
end end
defp check_diagonal(grid, {center_row, center_col}, {top_dr, top_dc}, {bottom_dr, bottom_dc}) do defp check_diagonal_pattern(
# Check top part and bottom part grid,
top_row = center_row + top_dr {start_row, start_col},
top_col = center_col + top_dc {end_row, end_col},
bottom_row = center_row + bottom_dr {center_row, center_col}
bottom_col = center_col + bottom_dc ) do
start_char = Enum.at(Enum.at(grid, start_row), start_col)
center_char = Enum.at(Enum.at(grid, center_row), center_col)
end_char = Enum.at(Enum.at(grid, end_row), end_col)
within_bounds?(grid, top_row, top_col) and # Check if we have M->A->S in this order
within_bounds?(grid, bottom_row, bottom_col) and # Or S->A->M in this order
( (start_char == "M" and center_char == "A" and end_char == "S") or
# Check normal orientation (M at top, S at bottom) (start_char == "S" and center_char == "A" and end_char == "M")
(Enum.at(Enum.at(grid, top_row), top_col) == "M" and
Enum.at(Enum.at(grid, bottom_row), bottom_col) == "S") or
# Check upside down orientation (S at top, M at bottom)
(Enum.at(Enum.at(grid, top_row), top_col) == "S" and
Enum.at(Enum.at(grid, bottom_row), bottom_col) == "M")
)
end end
@doc """ @doc """