diff --git a/Blink3.Core/Extensions/WordleExtensions.cs b/Blink3.Core/Extensions/WordleExtensions.cs index 316178d..12d0a88 100644 --- a/Blink3.Core/Extensions/WordleExtensions.cs +++ b/Blink3.Core/Extensions/WordleExtensions.cs @@ -14,8 +14,8 @@ public static class WordleExtensions /// The word guess entered by a player. public static void ProcessGuess(this Wordle wordle, WordleGuess guess) { - List correctIndices = []; - List misplacedIndices = []; + ICollection correctIndices = []; + ICollection misplacedIndices = []; guess.MarkCorrectLetters(wordle, correctIndices); guess.MarkMisplacedLetters(wordle, correctIndices, misplacedIndices); diff --git a/Blink3.Core/Extensions/WordleGuessExtensions.cs b/Blink3.Core/Extensions/WordleGuessExtensions.cs index bb610d4..6e450ef 100644 --- a/Blink3.Core/Extensions/WordleGuessExtensions.cs +++ b/Blink3.Core/Extensions/WordleGuessExtensions.cs @@ -1,6 +1,8 @@ using Blink3.Core.Entities; using Blink3.Core.Enums; +// ReSharper disable SuggestBaseTypeForParameter + namespace Blink3.Core.Extensions; /// @@ -39,27 +41,67 @@ public static void MarkMisplacedLetters(this WordleGuess guess, Wordle wordle, { string word = guess.Word; string wordToGuess = wordle.WordToGuess; - Dictionary checkedLettersCount = new(); // number of times a letter has been processed - for (int i = 0; i < word.Length; i++) - { - char letter = word[i]; - if (guess.Letters[i].State == WordleLetterStateEnum.Correct) continue; + Dictionary checkedLettersCount = new(); + Dictionary> charIndicesMap = GenerateCharIndicesMap(wordToGuess); - checkedLettersCount.TryAdd(letter, 0); - int letterOccurrences = wordToGuess.AllIndexesOf(letter).Count; + for (int i = 0; i < word.Length; i++) + MarkSpecificLetter(guess, word, correctIndices, misplacedIndices, checkedLettersCount, charIndicesMap, i); + } - if (checkedLettersCount[letter] >= letterOccurrences) continue; - checkedLettersCount[letter]++; + /// + /// Generates a character indices map for a given word. + /// + /// The word to generate the character indices map for. + /// A dictionary with characters as keys and lists of indices as values. + private static Dictionary> GenerateCharIndicesMap(string wordToGuess) + { + Dictionary> charIndicesMap = new(wordToGuess.Length); - List indices = wordToGuess.AllIndexesOf(letter); - foreach (int index in indices.Where(index => - !(correctIndices.Contains(index) || misplacedIndices.Contains(index)))) + for (int i = 0; i < wordToGuess.Length; i++) + { + if (!charIndicesMap.TryGetValue(wordToGuess[i], out List? value)) { - guess.Letters[i].State = WordleLetterStateEnum.Misplaced; - misplacedIndices.Add(index); - break; + value = new List(); + charIndicesMap[wordToGuess[i]] = value; } + + value.Add(i); } + + return charIndicesMap; + } + + /// + /// Marks a specific letter in the WordleGuess object based on given parameters. + /// + /// The WordleGuess object + /// The word from the guess + /// The collection of correct indices + /// The collection of misplaced indices + /// The dictionary of checked letters count + /// The dictionary mapping characters to indices + /// The index of the letter to mark + private static void MarkSpecificLetter(WordleGuess guess, string word, ICollection correctIndices, + ICollection misplacedIndices, Dictionary checkedLettersCount, + Dictionary> charIndicesMap, int i) + { + char letter = word[i]; + if (guess.Letters[i].State == WordleLetterStateEnum.Correct) return; + + checkedLettersCount.TryAdd(letter, 0); + checkedLettersCount[letter]++; + + if (!charIndicesMap.TryGetValue(letter, out List? value)) return; + + foreach (int index in value.Where(index => + !correctIndices.Contains(index) && !misplacedIndices.Contains(index))) + { + guess.Letters[i].State = WordleLetterStateEnum.Misplaced; + misplacedIndices.Add(index); + break; + } + + if (checkedLettersCount[letter] >= value.Count) charIndicesMap.Remove(letter); } } \ No newline at end of file