Skip to content

Instantly share code, notes, and snippets.

@josephturnerjr
Created June 22, 2012 20:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josephturnerjr/2974938 to your computer and use it in GitHub Desktop.
Save josephturnerjr/2974938 to your computer and use it in GitHub Desktop.
Hanging solver in Python vs. Coffeescript
# Hash-based set implementation from the Coffeescript cookbook
# http://coffeescriptcookbook.com/chapters/arrays/removing-duplicate-elements-from-arrays
Array::unique = ->
output = {}
output[@[key]] = @[key] for key in [0...@length]
value for key, value of output
class Solver
constructor: (data) ->
words = new String(data).trim().split(' ')
words = (x.toLowerCase() for x in words)
words = words.unique()
# Parse the words into lengths
lengths = (w.length for w in words).unique()
word_sets = (x for x in words when x.length == l for l in lengths)
@words = {}
@words[key] = word_sets[i] for key, i in lengths
solve: (query, tried) ->
# Query is . for unknowns, letters filled in as appropriate
# The words can't contain letters that are already there
# Also not the letters we've already tried
bad_chars = (x for x in query when x != '.')
bad_chars = bad_chars.concat((if tried.length then tried.join("") else [])).unique()
# Build a pattern for those letters
off_limits = bad_chars.join("")
ignore_pattern = "[^#{off_limits}]"
# Replace the wildcards with the pattern
reg = new RegExp(query.replace /\./g, ignore_pattern)
# Words that match the resulting pattern
possibilities = []
if @words[query.length]?
possibilities = (x for x in @words[query.length] when x.match(reg))
return new SolverResults(possibilities, bad_chars)
class SolverResults
constructor: (possibilities, bad_chars) ->
@possibilities = possibilities
@bad_chars = bad_chars
get_possibilities: ->
return @possibilities
get_letter_freqs: ->
if not @scores?
if @possibilities.length is 0
@scores = []
else
# Calculate the most likely unguessed letter
# ALL OF THE LETTERS!
concat = @possibilities.join("").split("")
# Calculate the letter frequencies for each non-guessed letter,
# the max being the most likely
chars = (x for x in concat.unique() when x not in @bad_chars)
@scores = ([(y for y in @possibilities when x in y).length, x] for x in chars)
@scores.sort((a,b) -> b[0] - a[0])
return @scores
import re
class Solver(object):
def __init__(self, data):
words = set(map(lambda x: x.lower(), data.split()))
# Parse the words into lengths
lengths = set(map(len, words))
word_sets = [filter(lambda x: len(x) == l, words) for l in lengths]
self.words = dict(zip(lengths, word_sets))
def solve(self, query, tried):
# Query is . for unknowns, letters filled in as appropriate
# The words can't contain letters that are already there
# Also not the letters we've already tried
bad_chars = set(filter(lambda x: x != '.', query) + "".join(tried))
# Build a pattern for those letters
off_limits = "".join(bad_chars)
ignore_pattern = "[^%s]" % (off_limits,)
# Replace the wildcards with the pattern
reg = re.sub('\.', ignore_pattern, query)
# Words that match the resulting pattern
possibilities = filter(lambda x: re.match(reg, x),
self.words[len(query)])
return SolverResults(possibilities, bad_chars)
class SolverResults(object):
def __init__(self, possibilities, bad_chars):
self.possibilities = possibilities
self.bad_chars = bad_chars
self.scores = None
def get_possibilities(self):
return self.possibilities
def get_letter_freqs(self):
if not self.scores:
if not self.possibilities:
self.scores = []
else:
# Calculate the most likely unguessed letter
# ALL OF THE LETTERS!
chars = set("".join(self.possibilities)) - self.bad_chars
# Calculate the letter frequencies for each non-guessed letter,
# the max being the most likely
self.scores = [[len(filter(lambda w: c in w, self.possibilities)), c] for c in chars]
self.scores.sort(reverse=True)
return self.scores
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment