From df41b278f8d477eccb016302b2581f98f5a3af71 Mon Sep 17 00:00:00 2001 From: Ruidy Date: Wed, 4 Dec 2024 12:52:57 +0100 Subject: [PATCH] feat: implement solution to the example --- lib/advent_code2024/solutions/day04/day4.ex | 77 +++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 lib/advent_code2024/solutions/day04/day4.ex diff --git a/lib/advent_code2024/solutions/day04/day4.ex b/lib/advent_code2024/solutions/day04/day4.ex new file mode 100644 index 0000000..54e8bef --- /dev/null +++ b/lib/advent_code2024/solutions/day04/day4.ex @@ -0,0 +1,77 @@ +defmodule AdventCode2024.Solutions.Day04 do + def count_word_occurrences(grid, word) do + grid + |> Enum.map(&String.graphemes/1) + |> find_word(word) + end + + defp find_word(grid, word) do + directions = [ + # Right + {0, 1}, + # Down + {1, 0}, + # Left + {0, -1}, + # Up + {-1, 0}, + # Down-right diagonal + {1, 1}, + # Up-left diagonal + {-1, -1}, + # Down-left diagonal + {1, -1}, + # Up-right diagonal + {-1, 1} + ] + + grid + |> Enum.with_index() + |> Enum.reduce(0, fn {row, row_idx}, acc -> + row + |> Enum.with_index() + |> Enum.reduce(acc, fn {_, col_idx}, acc_inner -> + acc_inner + count_word_from(grid, word, {row_idx, col_idx}, directions) + end) + end) + end + + @doc """ + Counts the occurrences of a word in all possible directions from a given starting position in the grid. + + ## Parameters + - grid: A 2D list representing the word search grid. + - word: The word to be searched for. + - row: The starting row index. + - col: The starting column index. + - directions: A list of tuples representing the directions to search in. + + ## Returns + - The number of times the word is found from the given starting position in the grid. + """ + defp count_word_from(grid, word, {row, col}, directions) do + directions + |> Enum.reduce(0, fn direction, acc -> + if find_word?(grid, word, {row, col}, direction) do + acc + 1 + else + acc + end + end) + end + + defp find_word?(grid, word, {row, col}, {d_row, d_col}) do + word + |> String.codepoints() + |> Enum.with_index() + |> Enum.all?(fn {char, i} -> + new_row = row + i * d_row + new_col = col + i * d_col + within_bounds?(grid, new_row, new_col) && Enum.at(Enum.at(grid, new_row), new_col) == char + end) + end + + defp within_bounds?(grid, row, col) do + row >= 0 && row < length(grid) && col >= 0 && col < length(Enum.at(grid, 0)) + end +end