As it stands, this is not a valid answer, as it accesses the word list. I'm currently working on a version that doesn't do so, but it might take a while.
A joint submission from user PragTob and myself.
MAX_TURNS = 6
words_by_lengthfrequencies = File.read('wordlist.txt').split.group_by &:length{?t=>[3,48,145,214,252,266,249,223,191,142,63,44,16,1,0,1],?h=>[2,14,81,125,85,91,60,42,30,14,11,6,1,1],?e=>[5,49,260,316,456,408,328,279,202,125,50,32,12,0,0,1],?a=>[4,60,211,259,249,266,253,192,152,111,51,42,15,1,0,1],?n=>[4,30,120,136,214,252,238,214,189,128,59,45,16,0,0,1],?d=>[1,25,100,104,131,123,131,81,63,36,14,15,7,1],?f=>[2,13,51,58,64,67,41,40,28,18,11,9,3,1],?o=>[9,44,150,165,195,220,214,168,155,104,46,37,14,1,0,1],?r=>[1,25,140,246,312,310,263,206,150,95,45,32,11,1],?y=>[3,29,41,58,86,94,83,63,52,31,21,12,2],?u=>[2,23,67,117,126,154,107,97,85,48,27,16,2,0,0,1],?b=>[2,22,53,60,72,59,41,30,36,16,7,6,1],?i=>[3,38,143,179,223,299,270,241,205,134,64,44,16,1,0,1],?s=>[3,23,129,176,195,208,177,136,117,71,44,23,13,1],?c=>[0,12,68,122,146,194,180,163,130,85,49,25,7,0,0,1],?l=>[0,18,153,172,190,196,164,131,125,67,35,20,5,0,0,1],?g=>[1,19,42,75,82,104,78,60,39,30,12,10,0,1],?w=>[1,21,56,56,40,41,18,16,6,2,1,0,0,1],?m=>[2,10,77,68,119,94,104,76,68,45,15,17,8,0,0,1],?p=>[1,24,82,84,94,129,105,88,99,56,24,11,7],?k=>[1,6,65,37,28,24,6,10,3,4],?j=>[0,5,5,6,7,6,5,6,2,0,1,1],?x=>[0,6,4,7,15,22,13,16,9,9,2,2],?v=>[0,3,21,39,47,58,63,42,40,23,10,9,2],?z=>[0,0,3,3,3,5,2,3,0,0,1],?q=>[0,0,1,9,5,13,8,3,5,4,3,2]}
while !(input=gets.chomp)['END']
current_turns = MAX_TURNS
won = false
fitting_wordschars = words_by_length[inputfrequencies.length]
characters_used =keys.sort_by '_'{|c|
while -(current_turnsfrequencies[c][input.length-2] >|| 0) && !won
pattern_regex = Regexp.new(input.gsub('_', "[^#{characters_used}]"))
fitting_words = fitting_words.select do |word|i=0
while (current_turns > 0) pattern_regex.match&& word!won
end
c=chars[i]
char_count =i Hash.new+= 01
fitting_words.each doputs |word|c
word.chars.uniq$stdout.each {|c|flush
old_input char_count[c] +== 1input
input }
end
chars = char_count.keys.reject {|c|
/[#{characters_used}]/.match c
}gets.sort_by {|c|-char_count[c]}chomp
characters_used << chars[0]
puts chars[0]
if input == $stdout.flushold_input
old_input current_turns -= input1
input # else
# = getsfrequencies[c][input.chomp
current_turnslength-2] -= 1
if input == old_inputend
won = !input[?_]
end
if won
words_by_length[input.length].delete input
end
end
Currently this takes about 13 seconds on my machine, but there is certainly room for some speed optimisation.Result:
score is 625, totalerr is 23196
It averages a score of about 3940This has 1672 characters and total error of 6050isn't golfed yet so we have ample room for algorithmic improvement.
I say "averages", because the algorithm depends on the orderFirst we store a hash of character frequencies (computed from the words usedword list) grouped by word length.
This is roughly how it works:
for each guess, we figure out all possible words from the given list, count in how many of them each character occurs and guess the most common one
here is how we determine "all possible words":
- we start with all words on word list
- every time we guess a word correctly, we delete it
- at each turn we also remove all words that do not fit the input pattern
- finally we remove all words where "blanks" in the input pattern correspond to characters we already guessed
It's getting late over here and that's currently the best method we can think of. We might be able to make minor improvements by including logic to throw out missed words as well (sayThen in each round we missed three words thatsimply sort all read _o_
atcharacters by the end,frequencies for the current length and there are three words like this left in our list, we could throw those out as well)try them from most common to least common one. But it seems thatUsing this might take at least as much code asapproach we already have, and the improvements may or may not be negligibleobviously fail every single word that has even just a medium common character.