/** * Compute Wordle feedback colors for a guess against the target word. * * Algorithm (Feedback Scoring Rule): * 1. Mark exact-position matches (green/'g'), decrement remaining letter count * 2. For remaining positions, mark as yellow/'y' if letter still has remaining count * 3. All other positions are gray/'x' * * Returns a 5-element array of 'g' | 'y' | 'x'. */ export function computeFeedback(target: string, guess: string): string[] { if (target.length !== 5 || guess.length !== 5) { throw new Error('Target and guess must be exactly 5 letters'); } const targetUpper = target.toLowerCase(); const guessUpper = guess.toLowerCase(); // Count letters in target const targetCounts: Record = {}; for (const ch of targetUpper) { targetCounts[ch] = (targetCounts[ch] ?? 0) + 1; } const result: string[] = Array(5).fill('x'); // Pass 1: greens (exact position matches) for (let i = 0; i < 5; i++) { if (guessUpper[i] === targetUpper[i]) { result[i] = 'g'; targetCounts[guessUpper[i]]--; } } // Pass 2: yellows (letter present but wrong position, remaining count) for (let i = 0; i < 5; i++) { if (result[i] === 'g') continue; // already matched const ch = guessUpper[i]; if ((targetCounts[ch] ?? 0) > 0) { result[i] = 'y'; targetCounts[ch]--; } } return result; }