Skip to content

Instantly share code, notes, and snippets.

@lesserhatch
Last active March 18, 2022 10:55
Show Gist options
  • Save lesserhatch/267a77c4e1a6a88c9385044bfd00f1aa to your computer and use it in GitHub Desktop.
Save lesserhatch/267a77c4e1a6a88c9385044bfd00f1aa to your computer and use it in GitHub Desktop.
Recursive Wordle Scorer in Elixir
defmodule Wordle.Impl.Game do
defstruct(
guessed_words: [],
incorrect_letters: MapSet.new(),
secret_word: "",
state: :initializing,
turns_left: 6
)
def guess_word(game, guess) when game.state == :playing do
guess = guess |> String.upcase()
game
|> update_guessed_words(guess)
|> update_incorrect_letters(guess)
|> decrement_turns_left
|> maybe_update_state(guess)
end
def guess_word(game, _guess) do
game
end
def new_game do
%Wordle.Impl.Game{
secret_word: Dictionary.random_word |> String.upcase,
state: :playing
}
end
defp decrement_turns_left(game) do
%{game | turns_left: game.turns_left - 1}
end
defp maybe_update_state(%Wordle.Impl.Game{secret_word: guess} = game, guess) do
%{game | state: :won}
end
defp maybe_update_state(%Wordle.Impl.Game{turns_left: 0} = game, _) do
%{game | state: :lost}
end
defp maybe_update_state(game, _), do: game
defp score_word(game, guess) do
score_word(
game.secret_word |> String.split("", trim: true),
guess |> String.split("", trim: true),
[]
)
end
defp score_word([], _, _), do: []
defp score_word(_, [], _), do: []
defp score_word([matching_letter | secret], [matching_letter | guess], unmatched) do
[{matching_letter, :correct} | score_word(secret, guess, unmatched)]
end
defp score_word([secret_letter | secret], [guess_letter | guess], unmatched) do
letter_score =
cond do
guess_letter in unmatched -> {guess_letter, :wrong_location}
guess_letter in guess -> {guess_letter, :not_in_word}
guess_letter in secret -> {guess_letter, :wrong_location}
true -> {guess_letter, :not_in_word}
end
unmatched =
if guess_letter in unmatched do
unmatched -- [guess_letter]
else
[secret_letter | unmatched]
end
[letter_score | score_word(secret, guess, unmatched)]
end
defp update_guessed_words(game, guess) do
%{game | guessed_words: [score_word(game, guess) | game.guessed_words]}
end
defp update_incorrect_letters(game, guess) do
new_incorrect_letters = (guess |> String.split("")) -- (game.secret_word |> String.split(""))
incorrect_letters = Enum.reduce(new_incorrect_letters, game.incorrect_letters, &(MapSet.put(&2, &1)))
%{game | incorrect_letters: incorrect_letters}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment