#(20$) Need by today, any help is appreciated!
5 messages · Page 1 of 1 (latest)
like this?
defmodule Boggle do
def boggle(game_board, words) do
Enum.reduce(words, %{}, fn word, acc ->
paths = find_paths_for_word(game_board, word)
if Enum.empty?(paths) do
acc # If no paths, keep the accumulator as is
else
Map.put(acc, word, paths) # Otherwise, add the found paths to the map
end
end)
end
defp find_paths_for_word(game_board, word) do
char_list = String.graphemes(word)
starts = get_starting_positions(game_board, hd(char_list))
# Use Enum.reduce/3 to collect all valid paths
Enum.reduce(starts, [], fn {row, col}, acc ->
paths = find_word_from_position(game_board, char_list, row, col, [], %{})
acc ++ paths # Only concatenate valid paths
end)
end
defp get_starting_positions(game_board, letter) do
for {row, row_index} <- Enum.with_index(game_board),
{cell, col_index} <- Enum.with_index(row),
cell == letter,
do: {row_index, col_index}
end
defp find_word_from_position(_board, [], row, col, path, _visited), do: [{row, col} | path]
defp find_word_from_position(board, [current_letter | remaining_letters], row, col, path, visited) do
if is_inside?(board, row, col) and not Map.has_key?(visited, {row, col}) and board[row][col] == current_letter do
new_visited = Map.put(visited, {row, col}, true)
neighbors(row, col)
|> Enum.filter(&is_inside?(board, elem(&1, 0), elem(&1, 1)))
|> Enum.reduce([], fn {n_row, n_col}, acc ->
acc ++ find_word_from_position(board, remaining_letters, n_row, n_col, [{row, col} | path], new_visited)
end)
else
[]
end
end
defp neighbors(row, col) do
for dx <- -1..1, dy <- -1..1, reduce: [] do
acc ->
if dx != 0 or dy != 0, do: [{row + dx, col + dy} | acc], else: acc
end
end
defp is_inside?(board, row, col) do
row >= 0 and row < length(board) and col >= 0 and col < length(Enum.at(board, row))
end
end