Skip to content

Instantly share code, notes, and snippets.

@Kenny2github
Created June 9, 2022 07:03
Show Gist options
  • Save Kenny2github/763e750656948bfd2b567f927db5a51e to your computer and use it in GitHub Desktop.
Save Kenny2github/763e750656948bfd2b567f927db5a51e to your computer and use it in GitHub Desktop.
Generate words for Squaredle - https://squaredle.app
defmodule Squaredle do
def find_word(row, col, word, board, past_path) do
coords = [
{row + 1, col + 1},
{row + 1, col + 0},
{row + 1, col - 1},
{row + 0, col + 1},
{row + 0, col - 1},
{row - 1, col + 1},
{row - 1, col + 0},
{row - 1, col - 1},
]
found = Enum.find(coords, fn {srow, scol} ->
if Enum.member?(past_path, {srow, scol}) do
false
else
find_word_guarded(srow, scol, word, board, past_path)
end
end)
found != nil
end
def find_word_guarded(row, _col, _word, board, _past_path)
when row < 0 or row >= tuple_size(board), do: false
def find_word_guarded(row, col, _word, board, _past_path)
when col < 0 or col >= tuple_size(elem(board, row)), do: false
def find_word_guarded(row, col, [letter], board, _past_path)
when board |> elem(row) |> elem(col) == letter, do: true
def find_word_guarded(row, col, [letter | word], board, past_path)
when board |> elem(row) |> elem(col) == letter do
find_word(row, col, word, board, [{row, col}] ++ past_path)
end
def find_word_guarded(_, _, _, _, _), do: false
def word_ok([letter | word], board) do
dim = tuple_size(board) - 1
found = Enum.find(
(for row <- 0..dim, col <- 0..dim, do: {row, col}),
fn {row, col} ->
if letter == board |> elem(row) |> elem(col) do
find_word(row, col, word, board, [{row, col}])
else
false
end
end
)
found != nil
end
def word_ok(word, board) when is_binary(word) do
word_ok(String.codepoints(word), board)
end
def make_board(str) do
str
|> String.trim("\n")
|> String.upcase()
|> String.split(~r"\r?\n")
|> Enum.map(&(&1 |> String.codepoints() |> List.to_tuple()))
|> List.to_tuple()
end
def load_words() do
File.read!("all_words.txt")
|> String.trim()
|> String.split()
|> MapSet.new()
end
def valid_words(board, upto \\ nil) do
letters = board |> String.trim() |> String.upcase()
letters = Regex.replace(~r"\s*", letters, "")
len = upto || byte_size(letters)
all_words = load_words()
board_t = make_board(board)
for n <- 4..len do
words = all_words
|> Enum.filter(&(byte_size(&1) == n))
|> Enum.map(&String.codepoints/1)
|> Enum.filter(&word_ok(&1, board_t))
{n, words}
end
end
def print_valid_words(board, upto \\ nil) do
for {n, words} <- valid_words(board, upto) do
IO.puts("#{n} letters:")
for word <- words do
IO.puts(" #{word}")
end
end
end
end
defmodule I do
def gets(prompt \\ "") do
case IO.gets(prompt) do
:eof -> ""
str -> String.trim(str, "\n")
end
end
end
board = Enum.join(
Stream.unfold(I.gets(
"Enter the board, rows separated by line breaks. End with a blank line.\n"
), fn
"" -> nil
line -> {line, I.gets()}
end), "\n"
)
board_t = Squaredle.make_board(board)
num = I.gets("Enter number of letters to get to (0 to skip, blank for all): ")
num = if num != "" do
String.to_integer(num)
else
byte_size(Regex.replace(~r"\s*", board, ""))
end
if num > 0, do: Squaredle.print_valid_words(board, num)
Enum.find(Stream.cycle([1]), fn _ ->
word = I.gets("Enter a word to check (blank to stop): ") |> String.upcase()
if word == "" do
true
else
word |> Squaredle.word_ok(board_t) |> IO.inspect()
false
end
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment