You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.9 KiB

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())