from collections import defaultdict
import re
from math import factorial
class Word:
def __init__(self, word):
self.word = word
self.r = ''
self.x = ''
self.guessed = ''
self.mask = re.sub(r'[a-z]', '_', word)
self.remaining = word
self.index = 0
self.won = False
self.lost = False
self.indexes = []
def isEnded(self):
return self.won or self.lost
def move(self, d):
while d[self.index] in self.guessed:
if d[self.index] in self.r:
self.index += 1
else:
R = 12-len(self.r)
X = 6-len(self.x)
try:
self.index += factorial(X+R)/factorial(R)/factorial(X)
except:
print self.word, self.guessed, self.r, self.x, self.index, self.mask, self.remaining
raise
self.index = (self.index%len(d))
def update(self, d):
# bestLetter may already have been guessed for this word
self.move(d)
while d[self.index] != '.' and not self.isEnded():
if d[self.index] in self.remaining:
self.r += d[self.index]
else:
self.x += d[self.index]
self.guessed += d[self.index]
self.indexes.append(self.index)
for letterIndex in range(len(self.mask)):
if self.word[letterIndex] == d[self.index]:
self.mask = self.mask[:letterIndex]+d[self.index]+self.mask[letterIndex+1:]
self.remaining = self.remaining.replace(d[self.index], '_')
if len(self.x) == 6:
self.lost = True
elif '_' not in self.mask:
self.won = True
else:
self.move(d)
class Words:
def __init__(self, words):
self.words = []
for word in words:
self.words.append(Word(word))
def allEnded(self):
for word in self.words:
if not word.isEnded():
return False
return True
def getBestIndex(self):
count = defaultdict(int)
bestCount = 0
bestIndex = 0
for word in self.words:
if not word.isEnded():
count[word.index]+=1
if count[word.index] > bestCount:
bestCount = count[word.index]
bestIndex = word.index
return bestIndex
def getBestLetter(self, index):
count = defaultdict(int)
bestCount = 0
bestLetter = ''
for word in self.words:
if word.isEnded() or word.index != index:
continue
for letter in word.remaining.replace('_',''):
count[letter] += 1
if count[letter] > bestCount:
bestCount = count[letter]
bestLetter = letter
return bestLetter
def update(self, bestIndex, bestLetter, d):
for word in self.words:
if not word.isEnded():
word.update(d)
def wins(self):
w = 0
for word in self.words:
if word.won:
w+=1
return w
def is_prime(n):
for i in range(3,n):
if n%i == 0:
return False
return True
bestWins = 0
bestD={}
for length in range(4001,1500,-2):
if not is_prime(length):
continue
d = ['.']*length
fff = open('wordlist.txt')
lines = fff.readlines()
fff.close()
ww = []
for line in lines:
w=line.strip()
if re.match(r'^[a-z]*$', w):
ww.append(w)
words = Words(ww)
while not words.allEnded():
bestIndex = words.getBestIndex()
bestLetter = words.getBestLetter(bestIndex)
# Update d
d[bestIndex] = bestLetter
# Move words
words.update(bestIndex, bestLetter, d)
wins = words.wins()
counts = defaultdict(int)
for l in d:
if l != '.':
counts[l]+=1
if counts[l] == max(counts.values()):
bestL=l
encoded = ''.join(d).replace('.',bestL).encode('zip').encode('base64')
newEntry = (len(encoded), length, encoded, ''.join(d).replace('.',bestL))
toRemove = []
include = True
for oldWins, oldEntry in bestD.items():
if oldWins < wins and oldEntry[0] >= newEntry[0]:
toRemove.append(oldWins)
if oldWins > wins and oldEntry[0] <= newEntry[0]:
include = False
for oldWins in toRemove:
bestD.pop(oldWins)
if include:
bestD[wins] = newEntry
print wins, len(encoded), length
for k in sorted(bestD.keys()):
print ' %d | %d | %s'%(k, bestD[k][0], bestD[k][3])