Example #1
0
	def getPlay(self, left, right, length=None, wordplays=None, gui=None):

		charades = []
		possible_lefts = [] # consist of word-certainty pairs
		possible_rights = [] # consist of just words (more convenient this way)
		# Check if any possible code keywords exist in either part.
		if wordplays is not None:
			for typ in ['initial', 'final']:
				try:
					for pos, word in enumerate(left):
						word = wordnet.stemmer.stem(word)
						if word in wordplays[typ].keywords:
							if len(left[:pos]) > 0:
								possible_lefts.append((wordplays[typ].getPlay(left[:pos]),1.0))
							if len(left[pos+1:]) > 0:
								possible_lefts.append((wordplays[typ].getPlay(left[pos+1:]),1.0))
				except KeyError:
					pass
				try:
					for pos, word in enumerate(right):
						word = wordnet.stemmer.stem(word)
						if word in wordplays[typ].keywords:
							if len(right[:pos]) > 0:
								possible_rights.append(wordplays[typ].getPlay(right[:pos]))
							if len(right[pos+1:]) > 0:
								possible_rights.append(wordplays[typ].getPlay(right[pos+1:]))
				except KeyError:
					pass

		# Add any abbreviations to the mix
		if len(left) == 1:
			possible_lefts.extend([(a, 1.0) for a in wordnet.getAbbreviations(left[0])])
		if len(right) == 1:
			possible_rights.extend(wordnet.getAbbreviations(right[0]))

		left, right = ('_'.join(left), '_'.join(right))
		# Try synonyms too
		if wordnet.exists(left):
			possible_lefts.extend([(s, -1.0) for s in wordnet.getSynonyms(left) if len(s.split('_'))==1])

		for possible_left, lsim in possible_lefts:
			for possible_right, rsim in [(pr, wordnet.calcSimilarity(pr, right))\
					for pr in self.getPossibleRights(possible_left, length) if wordnet.exists(pr)] +\
					[(pr, 1.0) for pr in possible_rights if wordnet.exists(possible_left + pr)]:
				if gui and gui.halt():
					return charades
				if rsim > 0:
					if lsim < 0:
						# Wait till now to compute this, as earlier we weren't sure if it'd get used.
						lsim = wordnet.calcSimilarity(possible_left, left)
					charades.append((possible_left+possible_right, rsim * lsim))
		return charades
Example #2
0
	def check(self, clue, token_sets, **kwargs):
		finals = []
		tokens = [token for token_set in token_sets.values() for token in token_set]
		for combo in self.getCombinations(tokens):
			soln = self.getPlay(combo)
			if wordnet.exists(soln) and clue.checkSolution(soln):
				finals.append(WordplaySolution(soln, self.__typ__, combo, self.calcCertainty(len(combo),len(tokens))))
		logger.debug('Final solutions found: %s' % finals)
		return finals
 def test_non_existence(self):
     for word in ['spellling', 'ish', 'veary', 'impoortent']:
         self.assertFalse(wordnet.exists(word),
                          '\'%s\' should not be in wordlist!' % word)
 def test_existence(self):
     for word in ['cryptic', 'crosswords', 'are', 'neat']:
         self.assertTrue(wordnet.exists(word),
                         '\'%s\' is not in wordlist!' % word)
	def parseClue(self, clue, length=None, typ=None, known_letters=None, brute_force=False, **kwargs):
		"""
		This is the core method that handles input clues, interprets them, then passes them off to other
		 modules to dissect. It then re-assimilates all solutions, sorts them, then returns them to the user.
		"""

		logger.info('Parsing clue: %s' % clue)

		# Convert to Clue object if it is not already.
		if not isinstance(clue, Clue):
			clue = Clue(clue, length, typ, known_letters)
			logger.debug('Converted clue to Clue object: %s' % clue)

		# Loop through all possible definitions.
		solutions = []
		raw_solns = set() # for bruteforcing later
		raw_definitions = [] # for bruteforcing later
		for defpos in filter(lambda x: x!=0, range(-DEFINITION_MAX_LEN, DEFINITION_MAX_LEN+1)):

			# Generate a list of possible solutions for chosen definition.
			# Defpos signifies how many words in the definition.
			# A negative value indicates to take words from end of string.
			definition = '_'.join(clue.tokens[0 if defpos > 0 else defpos : defpos if defpos > 0 else None])
			if not wordnet.exists(definition):
				continue

			raw_definitions.append([defpos,definition])

			# Generate possible wordplay interpretations. (Convert to a tree structure with keywords at nodes.)
			wpTokens = clue.tokens[0 if defpos < 0 else defpos:defpos if defpos < 0 else None]
			interpretations = self.interpret(clue, wpTokens)
			# Consider each interpretation.
			for kwpos, typs in interpretations.items():
				for typ, subplay in typs.items():
					if self.gui_thread:
						if self.gui_thread.halt():
							return solutions
						self.gui_thread.updateStatus(typ=typ)
					for soln in self.wordplays[typ].check(clue, subplay, wordplays=self.wordplays, gui=self.gui_thread, **kwargs):
						if self.gui_thread and self.gui_thread.halt():
							return solutions
						certainty = wordnet.calcSimilarity(soln.solution, definition) * soln.certainty
						if certainty > 0:
							solutions.append(
									Solution(clue,
												soln.solution,
												defpos,
												[(kwpos + (defpos if defpos > 0 else 0)) if kwpos >= 0 else -1, typ,
													' '.join(soln.applied_to)],
												certainty
									)
							)
							raw_solns.add(soln.solution)

		# Sort solutions by certainty score.
		solutions = sorted(solutions, key=lambda s: s.certainty, reverse=True)

		# Consider brute-forcing solutions.
		if brute_force:
			if known_letters is None:
				raise BruteForceWithoutKnownLettersException
			if self.gui_thread:
				if self.gui_thread.halt():
					return solutions
				self.gui_thread.updateStatus(typ='brute-forcing')
			# Get a brute-forced list of solutions.
			brute_solns = set(wordnet.getWordsWithPattern(clue.regex)) - raw_solns
			brute_forced_solutions = []
			for soln in brute_solns:
				if self.gui_thread and self.gui_thread.halt():
					return solutions
				soln_certainty = max([(0,None)]+[(wordnet.calcSimilarity(soln, d[1]), d[0]) for d in raw_definitions], key=lambda x:x[0])
				brute_forced_solutions.append(
						Solution(clue,
									soln,
									soln_certainty[1] if soln_certainty[0] > 0 else None,
									[-1, 'brute-forced',	'---'],
									soln_certainty[0]
						)
				)
			solutions.extend(sorted(brute_forced_solutions, key=lambda s: s.certainty, reverse=True))

		if solutions:
			logger.info('%i solution(s) found. Best solution is \'%s\' (certainty: %f)' % (len(solutions), solutions[0].solution, solutions[0].certainty))
		else:
			logger.info('Unsuccessful in resolving clue.')
		return solutions