Last active
May 28, 2016 00:50
-
-
Save XMPPwocky/2cde69b4fc0b46d03f2a8404459be117 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import re, string | |
from collections import Counter | |
def normalize_word(w): | |
return re.sub("[^a-z]", "", w.lower()) | |
def load_words(): | |
return list(map(normalize_word, open("/usr/share/dict/american-english-huge", "r").readlines())) | |
words = load_words() | |
whitelistchars = string.ascii_lowercase + "_" | |
init_char = string.ascii_lowercase | |
def feedback_to_re(fb, possible_chars): | |
cleaned = fb.strip().replace(" ", "") | |
for c in cleaned: | |
if c not in whitelistchars: return None | |
return re.compile("^"+cleaned.replace("_", "["+possible_chars+"]")+"$") | |
def feedback_to_chars(fb): | |
cleaned = fb.strip().replace(" ", "") | |
return cleaned.replace("_", "") | |
def refine_candidates(regex, candidates): | |
return set(filter(lambda w: regex.match(w) is not None, candidates)) | |
def find_candidates(regex): return refine_candidates(regex, words) | |
def optimal_guess(candidates, knownchars): | |
candidates = list(candidates) | |
if not candidates: return None | |
# they're all the same length | |
d = Counter() | |
for candidate in candidates: | |
for c in set(candidate): | |
if c not in knownchars: d[c] += 1 | |
total_freq = sum(d.values()) | |
avg_freq = float(total_freq)/len(set(d)) | |
def score(s): | |
return (s[0], s[1]) | |
return max(map(score, d.items()), key=lambda x: x[1])[0] | |
class Game: | |
def __init__(self, template): | |
self.possible_chars = init_char | |
self.knownchars = feedback_to_chars(template) | |
self.candidates = find_candidates(feedback_to_re(template, self.possible_chars)) | |
self.lastguess = None | |
self.template = template | |
def guess(self): | |
if len(self.candidates) == 1: return self.candidates.pop() | |
self.lastguess = optimal_guess(self.candidates, self.knownchars) | |
return self.lastguess | |
def wrong(self): | |
self.possible_chars = self.possible_chars.replace(self.lastguess, "") | |
self.update(self.template) | |
return self.guess() | |
def update(self, new_template): | |
self.template = new_template | |
self.candidates = refine_candidates(feedback_to_re(self.template, self.possible_chars), self.candidates) | |
self.knownchars = feedback_to_chars(self.template) | |
return self.guess() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment