Skip to content

Instantly share code, notes, and snippets.

@davidruffner
Last active September 4, 2017 23:07
Show Gist options
  • Save davidruffner/8f5422055f3ef1948a55212e2c9419f2 to your computer and use it in GitHub Desktop.
Save davidruffner/8f5422055f3ef1948a55212e2c9419f2 to your computer and use it in GitHub Desktop.
Scrabble Word Finder

Scrabble Word Finder

This little utility finds words that can be formed from your letters. You can specify what the word starts with and what it ends with, and the length of the gap in between.

It can by called on the terminal

$ python scrabbleWordFinder.py -m LARJ -e L
AL
ALL
JARL

The command line options are:

  • -m, myLetters
  • -s, startsWith
  • -e, endsWith
  • -g, gapLength
__author__ = 'David Ruffner'
import pandas as pd
import re
import collections
# Load up the standard scrabble words
# For faster performace copy the file locally.
#words = pd.read_csv('https://raw.githubusercontent.com/jmlewis/valett/master/scrabble/sowpods.txt', header=None)
words = pd.read_csv('sowpods.txt', header=None)
words = words.iloc[:,0]
def match(word, pattern):
"""
Test if word matches python regex pattern.
"""
if isinstance(word, basestring):
if pattern.match(word):
return True
else:
return False
else:
return False
def getNonZeroSplits(pattern, word):
"""
Get none empty splits from a regex pattern applied to a word.
"""
splits = pattern.split(word)
return [x for x in splits if x]
def split(word, startPattern, endPattern):
"""
Find leftover fragment after removing characters found by startPattern and endPattern.
"""
end = getNonZeroSplits(startPattern,word)[0]
middle = getNonZeroSplits(endPattern, end)[-1]
return middle
def inMyLetters(word, myLetters):
"""
Use counters (essentially multisets) to test whether the letters in word
can be created from and arrangement of myLetters.
"""
c1 = collections.Counter(word)
c2 = collections.Counter(myLetters)
if len(c1 - c2) == 0: # If len is 0 then c2 contains all the letters in c1
return True
else:
return False
def findWord(myLetters, startsWith, endsWith, gapLength):
"""
Finds a scrabble word that satisfies the conditions and can be
made from myLetters.
"""
# Handle empty arguments
if startsWith is not None:
startPattern = '^{}'.format(startsWith)
else:
startPattern = '^'
if endsWith is not None:
endPattern = '{}$'.format(endsWith)
else:
endPattern = '$'
if gapLength is not None:
midPattern = '.{{{0},{0}}}'.format(gapLength)
else:
midPattern = '.+'.format(startPattern, endPattern)
pattern = re.compile('{0}{1}{2}'.format(startPattern, midPattern, endPattern))
# Find all words that match patterns
matches = words.apply(match, convert_dtype=False, args=(pattern,))
# Find fragments of those words not in patterns
fragments = words[matches].apply(split, args=(re.compile(startPattern),
re.compile(endPattern)))
# See which of these words are in the myLetters
possibleWords = words.loc[fragments[fragments.apply(inMyLetters, args=(myLetters,))].index]
return possibleWords.values
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--myLetters', help='String of your scrabble letters')
parser.add_argument('-s', '--startsWith', help='Starting letters')
parser.add_argument('-e', '--endsWith', help='Ending letters')
parser.add_argument('-g', '--gapLength', type=int, help='Number of letters in gap')
args = parser.parse_args()
words = findWord(args.myLetters, args.startsWith, args.endsWith, args.gapLength)
for word in words:
print word
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment