Advertisement
GMan_LDN

Wordle Solver PoSH

Feb 1st, 2025
920
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # ====================================================================
  2. # Enhanced Wordle Solver – Six Guesses Maximum, Improved Suggestions,
  3. # and Global Letter Frequency Table.
  4. #
  5. # This script downloads a list of five–letter words (from the widely used
  6. # tabatkins/wordle-list), computes a global frequency table for the letters,
  7. # then enters a game loop.
  8. #
  9. # For each guess you enter:
  10. #   1. Your guess word (must be 5 letters)
  11. #   2. The feedback mask returned by the game (a string of 5 characters,
  12. #      using E for an exact match, I for a letter in the word but in the
  13. #      wrong position, and W for a wrong letter).
  14. #
  15. # Note:
  16. #   - If a letter is flagged I then that letter is definitely not in that
  17. #     position in the answer.
  18. #   - A letter flagged E may still appear elsewhere.
  19. #
  20. # The program filters the candidate words based on your feedback and uses
  21. # letter frequency (computed globally from the full dictionary as well as
  22. # from the candidate pool) to suggest good next guesses.
  23. #
  24. # You have six guesses to solve the puzzle.
  25. # ====================================================================
  26.  
  27. # --- Step 1. Download the word list ---
  28. $wordListUrl = "https://raw.githubusercontent.com/tabatkins/wordle-list/main/words"
  29. try {
  30.     Write-Host "Downloading word list..."
  31.     $response = Invoke-WebRequest -Uri $wordListUrl -UseBasicParsing -ErrorAction Stop
  32.     $content = $response.Content
  33. } catch {
  34.     Write-Error "Error downloading word list: $_"
  35.     exit
  36. }
  37. # Process the downloaded list: trim, lowercase, and keep only 5–letter words.
  38. $wordArray = $content -split "`n" | ForEach-Object { $_.Trim().ToLower() } | Where-Object { $_.Length -eq 5 }
  39. if (-not $wordArray -or $wordArray.Count -eq 0) {
  40.     Write-Error "Failed to build word list."
  41.     exit
  42. }
  43. Write-Host "Loaded" $wordArray.Count "five-letter words."
  44.  
  45. # --- Step 2. Build and Display a Global Letter Frequency Table ---
  46. function Build-LetterFrequency {
  47.     param (
  48.         [Parameter(Mandatory)]
  49.         [array]$words
  50.     )
  51.     $freq = @{}
  52.     foreach ($word in $words) {
  53.         # Only count each letter once per word (to favor words with unique letters).
  54.         ($word.ToCharArray() | Select-Object -Unique) | ForEach-Object {
  55.             if ($freq.ContainsKey($_)) { $freq[$_]++ } else { $freq[$_] = 1 }
  56.         }
  57.     }
  58.     return $freq
  59. }
  60.  
  61. $globalLetterFrequency = Build-LetterFrequency -words $wordArray
  62.  
  63. Write-Host "`nGlobal Letter Frequency Table (from all five-letter words):"
  64. $globalLetterFrequency.GetEnumerator() |
  65.     Sort-Object -Property Value -Descending |
  66.     Format-Table -Property Name, Value -AutoSize
  67.  
  68. # --- Step 3. Define the Wordle Feedback Function ---
  69. function Get-WordleFeedback {
  70.     <#
  71.       .SYNOPSIS
  72.          Simulates the Wordle feedback for a given secret and guess.
  73.       .DESCRIPTION
  74.          For a secret word and a guess, returns a 5–character string where:
  75.            E = the guessed letter is exactly correct (right letter, right spot),
  76.            I = the guessed letter is in the word but in a different spot,
  77.            W = the guessed letter is not in the word (or occurs too many times).
  78.          (A letter flagged I is disallowed from that position in the answer, while an E
  79.           does not preclude that letter appearing again.)
  80.     #>
  81.     param (
  82.         [Parameter(Mandatory)]
  83.         [string]$secret,
  84.         [Parameter(Mandatory)]
  85.         [string]$guess
  86.     )
  87.     $feedback = New-Object char[] 5
  88.  
  89.     # Build frequency counts for letters in the secret.
  90.     $letterCounts = @{}
  91.     for ($i = 0; $i -lt 5; $i++) {
  92.         $char = $secret[$i]
  93.         if ($letterCounts.ContainsKey($char)) {
  94.             $letterCounts[$char]++
  95.         } else {
  96.             $letterCounts[$char] = 1
  97.         }
  98.     }
  99.     # First pass: mark exact matches as "E".
  100.     for ($i = 0; $i -lt 5; $i++) {
  101.         if ($guess[$i] -eq $secret[$i]) {
  102.             $feedback[$i] = "E"
  103.             $letterCounts[$guess[$i]]--
  104.         }
  105.     }
  106.     # Second pass: for letters not already matched, mark "I" if the letter is present, else "W".
  107.     for ($i = 0; $i -lt 5; $i++) {
  108.         if ($feedback[$i] -ne "E") {
  109.             $char = $guess[$i]
  110.             if ($letterCounts.ContainsKey($char) -and $letterCounts[$char] -gt 0) {
  111.                 $feedback[$i] = "I"
  112.                 $letterCounts[$char]--
  113.             } else {
  114.                 $feedback[$i] = "W"
  115.             }
  116.         }
  117.     }
  118.     return -join $feedback
  119. }
  120.  
  121. # --- Step 4. Functions for Scoring and Suggestion ---
  122. # Score a word by summing the frequencies of its unique letters (using the given frequency table).
  123. function Get-GuessScore {
  124.     param (
  125.         [Parameter(Mandatory)]
  126.         [string]$word,
  127.         [Parameter(Mandatory)]
  128.         [hashtable]$frequencyTable
  129.     )
  130.     $score = 0
  131.     $uniqueLetters = $word.ToCharArray() | Select-Object -Unique
  132.     foreach ($letter in $uniqueLetters) {
  133.         if ($frequencyTable.ContainsKey($letter)) {
  134.             $score += $frequencyTable[$letter]
  135.         }
  136.     }
  137.     return $score
  138. }
  139.  
  140. # --- Step 5. Main Game Loop (Six Guesses Maximum) ---
  141. $candidateWords = $wordArray
  142. $guessHistory = @()
  143.  
  144. for ($attempt = 1; $attempt -le 6; $attempt++) {
  145.     Write-Host "`n---------------------------"
  146.     Write-Host "Attempt $attempt of 6"
  147.     if ($guessHistory.Count) {
  148.         Write-Host "Guess History:"
  149.         $guessHistory | ForEach-Object { Write-Host "$($_.Guess) => $($_.Mask)" }
  150.     }
  151.     Write-Host "Candidates remaining: $($candidateWords.Count)"
  152.     if ($candidateWords.Count -le 50) {
  153.         Write-Host "Candidate words: " ($candidateWords -join ", ")
  154.     }
  155.     if ($candidateWords.Count -eq 1) {
  156.         Write-Host "Only one candidate remains – the answer must be: $($candidateWords[0])"
  157.         break
  158.     }
  159.  
  160.     # For suggestion, if the candidate pool is large, use the full word list; otherwise use the candidate list.
  161.     $suggestPool = ($candidateWords.Count -gt 100) ? $wordArray : $candidateWords
  162.     $currentFrequency = Build-LetterFrequency -words $suggestPool
  163.     $scoredCandidates = foreach ($w in $candidateWords) {
  164.         [PSCustomObject]@{ Word = $w; Score = (Get-GuessScore -word $w -frequencyTable $currentFrequency) }
  165.     }
  166.     $suggestion = ($scoredCandidates | Sort-Object -Property Score -Descending | Select-Object -First 1).Word
  167.     Write-Host "Suggested guess: $suggestion"
  168.    
  169.     # Prompt for the guess.
  170.     $guess = Read-Host "Enter your guess word (or type 'exit' to quit)"
  171.     if ($guess.Trim().ToLower() -eq "exit") { break }
  172.     $guess = $guess.Trim().ToLower()
  173.     if ($guess.Length -ne 5) {
  174.         Write-Host "Your guess must be exactly 5 letters. Try again."
  175.         $attempt--
  176.         continue
  177.     }
  178.     # Prompt for the feedback mask.
  179.     $mask = Read-Host "Enter the feedback mask (E=exact, I=wrong spot but in word, W=wrong; e.g., EIWWI)"
  180.     $mask = $mask.Trim().ToUpper()
  181.     if ($mask.Length -ne 5 -or $mask -notmatch '^[EIW]{5}$') {
  182.         Write-Host "Invalid mask. It must be 5 characters (E, I, or W). Try again."
  183.         $attempt--
  184.         continue
  185.     }
  186.     $guessHistory += [PSCustomObject]@{ Guess = $guess; Mask = $mask }
  187.     if ($mask -eq "EEEEE") {
  188.         Write-Host "Congratulations! You solved the Wordle in $attempt attempt(s)!"
  189.         break
  190.     }
  191.     # Filter the candidate words: keep only those words that would produce the same feedback mask.
  192.     $candidateWords = $candidateWords | Where-Object { (Get-WordleFeedback -secret $_ -guess $guess) -eq $mask }
  193.     if ($candidateWords.Count -eq 0) {
  194.         Write-Host "No candidate words remain – please double-check your inputs."
  195.         break
  196.     }
  197. }
  198.  
  199. if ($attempt -gt 6) {
  200.     Write-Host "Maximum of 6 attempts reached – better luck next time!"
  201. }
  202. Write-Host "Exiting Wordle Solver. Happy puzzling!"
  203.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement