Skip to content

Instantly share code, notes, and snippets.

@mattak
Created February 2, 2022 09:38
Show Gist options
  • Save mattak/4016b0f62f0af55aa9dfe6cc9486c67f to your computer and use it in GitHub Desktop.
Save mattak/4016b0f62f0af55aa9dfe6cc9486c67f to your computer and use it in GitHub Desktop.
solve wordle puzzle
#!/usr/bin/ruby
# sample.
# {
# "q" => 0.00187529,
# "j" => 0.00309423,
# "z" => 0.00337553,
# "x" => 0.00407876,
# "v" => 0.0114393,
# "w" => 0.0173465,
# "f" => 0.0193624,
# "k" => 0.0195499,
# "g" => 0.0232536,
# "b" => 0.0241444,
# "h" => 0.0272386,
# "y" => 0.0273793,
# "m" => 0.0281763,
# "p" => 0.032677,
# "c" => 0.0332865,
# "u" => 0.0349742,
# "d" => 0.0427567,
# "n" => 0.0466948,
# "t" => 0.055368,
# "i" => 0.0560713,
# "l" => 0.0579466,
# "o" => 0.0627754,
# "r" => 0.067745,
# "a" => 0.0855602,
# "s" => 0.106892,
# "e" => 0.106939,
# }
def create_character_frequency(words)
freq = {}
total = 0
words.each do |word|
word.split("").each do |c|
freq[c] ||= 0
freq[c] += 1
total += 1
end
end
freq.keys.each do |c|
freq[c] = freq[c].to_f/total
end
return freq
end
def create_word_to_frequency_list(words, character_frequency)
word2freq_list = words.map do |it|
characters = it.split("")
f = characters.map do |x|
character_frequency[x]
end
[it,f.sum]
end.sort do |a,b|
b[1] - a[1]
end
return word2freq_list
end
def answer_response(answer, input)
result = input.map{|x| -1}
answer_hash = answer.reduce({}) {|h,x| h[x] ||= 0; h[x] += 1; h}
result = input.size.times.map do |i|
a = answer[i]
e = input[i]
if a == e && answer_hash[e] > 0 then
answer_hash[e] -= 1
1
else
result[i]
end
end
result = input.size.times.map do |i|
a = answer[i]
e = input[i]
if a != e && answer_hash.key?(e) && answer_hash[e] > 0 then
answer_hash[e] -= 1
0
else
result[i]
end
end
return result
end
def select_distinct_word(word2freq_list)
for word, freq in word2freq_list
characters = word.split("")
h={}
is_distinct = true
characters.each do |c|
h[c] ||=0
h[c] +=1
if h[c] > 1
is_distinct = false
break
end
end
if is_distinct
return word
end
end
word2freq_list[0][0]
end
def solve(answer, word2freq_list, max_try)
answers = answer.split("")
for try in 0...max_try do
if word2freq_list.size <= 0
return -1
end
input = select_distinct_word(word2freq_list)
inputs = input.split("")
ans = answer_response(answers, inputs)
return try if ans.all?(1)
word2freq_list = word2freq_list.delete_if {|x| x[0] == input }
inputs.each.with_index do |e, i|
if ans[i] == 1 then
word2freq_list = word2freq_list.filter {|w,f| w[i] == inputs[i]}
elsif ans[i] == 0 then
word2freq_list = word2freq_list.filter {|w,f| w.include?(inputs[i]) && w[i] != inputs[i]}
else ans[i] == -1
is_single = inputs.count{|x| x == inputs[i]} == 1
if is_single then
word2freq_list = word2freq_list.filter {|w,f| !w.include?(inputs[i])}
end
end
end
end
return -1
end
def solve_all(words, word2freq_list, max_try)
words.map do |word|
result = solve(word, word2freq_list.clone, max_try)
puts "#{word}\t#{result}"
end
end
# MAIN
if ARGV.size <= 0
puts <<__USAGE__
Usage:
ruby solve_wordle.rb <word_list_txt> <word>?
Example:
Solve all words
ruby solve_wordle.rb 5words.txt
Solve specific word
ruby solve_wordle.rb 5words.txt apple
Example of word list txt file:
apple
arrow
bolts
...
Word sets reference:
http://www.mieliestronk.com/wordlist.html
__USAGE__
exit 1
end
WORDLIST_FILE = ARGV[0]
MAX_TRY = 20
words = File.read(WORDLIST_FILE).chomp.split("\n").map{|x| x.chomp}
character_frequency = create_character_frequency(words)
word2freq_list = create_word_to_frequency_list(words, character_frequency)
if ARGV.size > 1
target_word = ARGV[1]
puts solve(target_word, word2freq_list, 20)
else
solve_all(words, word2freq_list, 20)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment