Wordle

I find the small projects often turn into great learning experiences.

I wanted a wordle filter. Got myself a wordlist of 14k 5-letter words and started writing. And there I was with a semi-complicated regexp checking every line. It worked. It was fast.

Still. I wanted to pre-filter the list using grep. I haven’t used grep more than the very simplest application. Now I had to look into -E, -e, -v and.. buffering?

I settled on awk for the inclusion. The /pat/ && /pat/ looks better than the alternatives. For exclusion: anti-grep using -v '[CHARS]'. In most cases the number of words are reduced to some hundred before Ruby filters positions.
(at least that was true before I introduced -b.)

# Example usage:
#   ruby wordle_search.rb -i NOX -e WAZEURS -p .OX.N
#
#   -i letters that must be included
#   -e letters that can't be included
#   -p letters with fixed position
#       Ex: .A..S (A and S are positioned at 2 and 5 respectivly)
#           .B    (no need to fill out to .B...)
#   -v be verbose (debug info)
#   -b show top-10 best guess (that introduces most new chars)

require 'rationalist'

args = Rationalist.parse(ARGV,
  alias: {include: :i, exclude: :e, position: :p, verbose: :v, best_guess: :b},
  default: {position: '.....'},
  string: [:include, :exclude, :position],
  boolean: [:verbose, :best_guess]
)

present = args[:i]
not_present = args[:e]

FILE = 'wordle_words.txt'
PRESENT = present.chars.map { '/%s/' % it }.join(' && ')
# 'IOR' become: '/I/ && /O/ && /R/'
NOT = not_present
p ['PRESENT', PRESENT], ['NOT', NOT] if args[:v]
p ['REX', "awk '#{PRESENT}' #{FILE} | grep -v '[#{NOT}]'"] if args[:v]

`awk '#{PRESENT}' #{FILE} | grep -v '[#{NOT}]'`
  .split("\n").tap { p 'words: %s' % it.size if args[:v] }
  .each {|ln| if /^#{args[:p]}/ =~ ln; p ln end }

if args[:b]
  wrds = `grep -v [#{present + not_present}] #{FILE}`.split("\n")
  puts '-'*80, 'BEST GUESSES (TOP-10)', '-'*80
  p wrds.map {
    [it, it.tr(present + not_present, '').chars.uniq.join.size]
  }.sort_by { -it[1] }[..10]
end

Example: ruby wordle_search.rb -i OXN -e WAZEURS -p .OX.N -b

Output: TOXIN (+ top-10 best guesses for next word)

Test-game (first guess is mine)

GUESS         PLACE  INC   EXCL
-------------------------------------------
BACON                +:A   -:BCNO
PURSE         *:E    +:AE  -:PRSUBCNO
WIFTY         *:E    +:AE  -:FITWYPRSUBCNO
VEALE         *:AE   +:AEL -:VFITWYPRSUBCNO
GLAZE         *GLAZE

2025-05-01
Tried it again and used ‘AEONS’ as my first word.
Then ‘MILKY’, ‘DUTCH’.. setteling on ‘URINE’.