Last active
March 18, 2022 10:55
-
-
Save lesserhatch/267a77c4e1a6a88c9385044bfd00f1aa to your computer and use it in GitHub Desktop.
Recursive Wordle Scorer in Elixir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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