import os import sys import time from trie import Trie DEBUG = os.environ.get('DEBUG', '') == '1' def main(): dim = int(os.environ.get('DIM', '3')) words_dat_file = os.environ.get('WORDS_DAT', 'words-en.dat') edges = list(map(lambda s: s.strip(), sys.stdin.read().split())) edge_map = {} valid_words = Trie.from_dat_file(words_dat_file) if len(edges) % dim != 0: raise ValueError('edges length={!r} not divisible by dim={!r}'.format( len(edges), dim)) for row in range(0, dim): for col in range(0, dim): idx = (row * dim) + col if idx >= len(edges): continue edge_map[(row, col)] = Edge((row, col), edges[idx]) for (row, col), edge in edge_map.items(): for sibling in ((row, col - 1), (row, col + 1), (row - 1, col), (row + 1, col), (row - 1, col - 1), (row - 1, col + 1), (row + 1, col + 1), (row + 1, col - 1)): debug('checking {!r} sibling {!r}'.format((row, col), sibling)) if edge_map.get(sibling) is not None: edge.siblings.add(edge_map[sibling]) debug(' added sibling {!r} to {!r}'.format(sibling, edge)) for origin in sorted(edge_map.keys()): for dest in sorted(edge_map.keys()): if origin == dest: continue debug('getting paths from origin={!r} to dest={!r}'.format( origin, dest)) for path in dfs_paths(edge_map, valid_words, origin, dest): print(''.join(list(map(lambda e: edge_map[e].value, path)))) return 0 class Edge: def __init__(self, id_, value, siblings=None): self.id = id_ self.value = value self.siblings = siblings if siblings is not None else set() def __repr__(self): return 'Edge({!r}, {!r}, siblings={!r})'.format( self.id, self.value, set(map(lambda s: s.id, self.siblings))) @property def sibling_ids(self): return set(map(lambda s: s.id, self.siblings)) def dfs_paths(edge_map, valid_words, origin, dest, path=None): if path is None: debug(' starting new path from {!r}'.format(origin)) path = [origin] if origin == dest: debug(' origin={!r} reached dest={!r}, yielding path'.format( origin, dest)) if len(path) > 2 and len(path) < 17: yield path if ''.join(path) not in valid_words: return next_steps = edge_map[origin].sibling_ids - set(path) if not next_steps: return debug(' origin={!r} dest={!r} checking next steps in {!r}'.format( origin, dest, next_steps)) for next_step in edge_map[origin].sibling_ids - set(path): yield from dfs_paths(edge_map, next_step, dest, path + [next_step]) def debug(msg): if not DEBUG: return print(msg, file=sys.stderr) if __name__ == '__main__': sys.exit(main())