- 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]) 
-