import re try: sum = __builtins__.sum except AttributeError: sum = __builtins__["sum"] RINGS = [ring.lower() for ring in 'BDMJPRSTLN', 'AEIOUYRTLH', 'ACDEORSTLN', 'DHKYRSTLNE'] rx_string = "^" + "".join( ("[" + ring + "]" for ring in RINGS)) + "$" print rx_string rx = re.compile(rx_string) for s in "BAAD", "BAAQ", "ABAAD", "baad", "baada", "abaad": if rx.match(s): print s, "YES" else: print s, "NO" print dictionary = (line.rstrip('\n') for line in file("/usr/share/dict/words", "r")) matchwords = [word for word in dictionary if rx.match(word)] print len(matchwords), "matching words" NUMDICTS = [ {letter: position for position, letter in enumerate(ring)} for ring in RINGS ] def unique_key(s): nums = [numdict[letter] for numdict, letter in zip(NUMDICTS, s)] return tuple( (num - nums[0]) % len(RINGS[0]) for num in nums[1:] ) for word in "baad", "bean", "salt", "noon": print word, unique_key(word) from collections import defaultdict GROUPS = defaultdict(list) for word in matchwords: GROUPS[unique_key(word)].append(word) GROUPS_OF_3 = [words for key, words in GROUPS.iteritems() if len(words) == 3] print len(GROUPS), "distinct groups of words" print len(GROUPS_OF_3), "groups of three words" for words in GROUPS_OF_3: print unique_key(words[0]), " ", " ".join(words)