fix: test are passing for part 2

This commit is contained in:
Ruidy 2024-12-04 17:48:19 +01:00
parent 1d6fdd25a8
commit 11d5af98db
No known key found for this signature in database
GPG key ID: E00F51288CB857CC

View file

@ -62,7 +62,7 @@ defmodule AdventCode2024.Solutions.Day04 do
end
defp within_bounds?(grid, row, col) do
row >= 0 && row < length(grid) && col >= 0 && col < length(Enum.at(grid, 0))
row >= 0 and row < length(grid) and col >= 0 and col < length(Enum.at(grid, 0))
end
@doc """
@ -85,68 +85,76 @@ defmodule AdventCode2024.Solutions.Day04 do
def solve_part2(_input_file) do
end
def count_x_mas(grid) when is_list(grid) do
# Convert string rows to character grid
char_grid = Enum.map(grid, &String.graphemes/1)
rows = length(char_grid)
cols = length(Enum.at(char_grid, 0))
def count_x_mas(grid) do
processed_grid = Enum.map(grid, &String.graphemes/1)
# Check each possible center position
for row <- 1..(rows - 2),
col <- 1..(cols - 2),
reduce: 0 do
acc ->
if is_x_mas_pattern?(char_grid, {row, col}) do
acc + 1
processed_grid
|> Enum.with_index()
|> Enum.reduce(0, fn {row, row_idx}, acc ->
row
|> Enum.with_index()
|> Enum.reduce(acc, fn {cell, col_idx}, acc_inner ->
if cell == "A" do # Start from the center A
acc_inner + check_x_patterns(processed_grid, {row_idx, col_idx})
else
acc
acc_inner
end
end
end)
end)
end
defp is_x_mas_pattern?(grid, {row, col}) do
# Get the center character first
center = get_char(grid, row, col)
if center != "A", do: false,
else: check_diagonals(grid, row, col)
end
defp check_diagonals(grid, row, col) do
# Define the four diagonal directions from center
diagonals = [
[{-1, -1}, {1, 1}], # top-left to bottom-right
[{-1, 1}, {1, -1}], # top-right to bottom-left
]
# For each diagonal pair, check if either forms a valid MAS pattern
Enum.any?(diagonals, fn [d1, d2] ->
chars1 = get_diagonal_chars(grid, row, col, d1)
chars2 = get_diagonal_chars(grid, row, col, d2)
case {chars1, chars2} do
{[c1, "A", c3], [c4, "A", c6]} when not is_nil(c1) and not is_nil(c3) and not is_nil(c4) and not is_nil(c6) ->
(is_mas?(c1, c3) and is_mas?(c4, c6)) or
(is_mas?(c3, c1) and is_mas?(c6, c4))
_ -> false
defp check_x_patterns(grid, {row, col}) do
# Check both 1-step and 2-step patterns
[1, 2]
|> Enum.reduce(0, fn step, acc ->
if check_x_pattern(grid, {row, col}, step) do
acc + 1
else
acc
end
end)
end
defp get_diagonal_chars(grid, row, col, {dr, dc}) do
[
get_char(grid, row - dr, col - dc),
get_char(grid, row, col),
get_char(grid, row + dr, col + dc)
]
defp check_x_pattern(grid, {row, col}, step) do
# Check if we can form an X pattern with MAS on both diagonals
check_diagonal(grid, {row, col}, {-step, -step}, {step, step}) and # top-left to bottom-right
check_diagonal(grid, {row, col}, {-step, step}, {step, -step}) # top-right to bottom-left
end
defp get_char(grid, row, col) do
if within_bounds?(grid, row, col) do
Enum.at(Enum.at(grid, row), col)
end
defp check_diagonal(grid, {center_row, center_col}, {top_dr, top_dc}, {bottom_dr, bottom_dc}) do
# Check top part and bottom part
top_row = center_row + top_dr
top_col = center_col + top_dc
bottom_row = center_row + bottom_dr
bottom_col = center_col + bottom_dc
within_bounds?(grid, top_row, top_col) and
within_bounds?(grid, bottom_row, bottom_col) and
(
# Check normal orientation (M at top, S at bottom)
(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
defp is_mas?(first, last) do
first == "M" and last == "S"
@doc """
Reads a grid from a file and counts the occurrences of a word using `count_word/2`.
## Parameters
- file_path: The path to the file containing the grid.
- word: The word to be searched for.
## Returns
- The number of times the word is found in the grid.
"""
def count_word_from_file(file_path, word) do
file_path
|> File.stream!()
|> Enum.map(&String.trim/1)
|> Enum.map(&String.graphemes/1)
|> count_word_occurrences(word)
end
end