Created
February 2, 2022 09:38
-
-
Save mattak/4016b0f62f0af55aa9dfe6cc9486c67f to your computer and use it in GitHub Desktop.
solve wordle puzzle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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