This is Wordle with a fixed word list. You guess a word from the list, the system tells you how many characters are in the exact right position, and you use that feedback to narrow down which word is the secret. You have a limited number of guesses, so the order of guesses matters.
One fact drives every approach. After guessing word W and receiving a match count of k from the Master, the secret has exactly k positional matches with W. Any word in the list that does not have exactly k positional matches with W cannot be the secret, so we eliminate it. This guess-and-filter loop is the foundation. The remaining question is which word to guess next to eliminate the most candidates.
words.length <= 100 -> The word list is small. Even O(n^2) work per guess stays under 10,000 comparisons.words[i].length == 6 -> Comparing two words is a fixed 6-character loop, so a single comparison is O(1).10 <= allowedGuesses <= 30 -> With at least 10 guesses for up to 100 words, eliminating one word per guess is not enough. The strategy has to shrink the candidate list faster than that.secret exists in words -> The answer is always in the candidate list, so we never construct words from scratch.The simplest strategy is to pick any word from the candidate list, guess it, and use the Master's feedback to eliminate impossible candidates. No selection logic is needed to get started; picking the first word in the list works.
Filtering works because the match count is symmetric and exact. If we guess word W and the Master returns k, the secret has exactly k characters matching W in the same positions. A word with 2 positional matches against W cannot be the secret when the Master reported 3, so we drop it. The secret always survives this filter because it has exactly k matches with W by definition.
After filtering, we repeat with the smaller candidate list. Each round guesses one word and removes it along with every incompatible word, until only the secret remains.
master.guess(guess) and store the match countmatch(word, guess) == matchCountallowedGuesses guesses.The weakness here is the selection strategy. Picking the first word wastes a guess when that word has the same match count with every other candidate, since the filter then removes only the guessed word itself. The next approach picks words that split the candidates into smaller groups.
A simple probability argument leads to a heuristic that works well before reaching for full game theory. For two random 6-letter words, each position has a 1/26 chance of matching, so the probability of zero total matches is (25/26)^6, about 79%. Roughly four out of five random word pairs share no character in any position.
That skew matters for filtering. When we guess a word and get 0 matches back, we keep only words with 0 matches against the guess. Because most word pairs have 0 matches, this group is usually the largest, and a large surviving group means weak elimination.
The heuristic falls out of this: for each candidate, count how many other candidates have 0 matches with it, then guess the candidate with the fewest zero-match partners. That word shares at least one positional character with the most other candidates. Guessing it keeps the dangerous 0-match group small, and the non-zero outcomes are smaller still.
master.guess() with the selected wordmatch(word, guess) == matchCountThe zero-match heuristic only looks at one of the seven possible match outcomes. A word can have few zero-match partners and still leave a large 3-match group. The next approach scores every outcome for each candidate and picks the word that minimizes the worst case.
Treat the secret as an adversary. We pick a guess, and the adversary effectively chooses the outcome by deciding which match count comes back. The goal is to minimize our worst case across every outcome the adversary could force.
For each candidate word W, consider guessing it. The other candidates split into groups by their match count with W: the 0-match group, the 1-match group, and so on up to the 5-match group (a 6-match means W is the secret). After we guess W and receive a match count, the candidate list shrinks to exactly the group with that count.
The worst case for guessing W is the size of its largest group, because the adversary can always report the count that leaves the most candidates. If W splits candidates into groups of sizes [15, 3, 2, 1], the worst case is 15 survivors. If word X splits them into [6, 5, 5, 4], its worst case is 6.
The minimax strategy picks the word whose largest group is smallest, minimizing the most candidates that can survive a single guess. For n up to 100, this converges in roughly 5 to 6 guesses, well inside the allowed budget.
Minimax changes which word we guess, not the filter that follows it. The secret has some fixed match count k with whatever word W we guess, so the secret always lands in the k-group and survives filtering. That holds for any selection rule, which is why all three approaches are correct and differ only in how many guesses they take. The minimax choice never grows the candidate list; in the worst case it leaves the largest group, and we bounded that group to be as small as possible.
master.guess() with the selected wordmatch(word, guess) == matchCountallowedGuesses rounds. With n <= 100, a single round is at most 10,000 word comparisons.