text: text = 'iila hhun erud dote'
  grid = text.split()
  nrows, ncols = len(grid), len(grid[0])
  
  # A dictionary word that could be a solution must use only the grid's
  # letters and have length >= 3. (With a case-insensitive match.)
  import re
  alphabet = ''.join(set(''.join(grid)))
  bogglable = re.compile('[' + alphabet + ']{3,}$', re.I).match
  
  words = set(word.rstrip('\n') for word in open('words.txt') if bogglable(word))
  prefixes = set(word[:i] for word in words for i in range(2, len(word) + 1))
  
  
  def solve():
  	for y, row in enumerate(grid):
  		for x, letter in enumerate(row):
  			for result in extending(letter, ((x, y),)):
  				yield result
  
  
  def extending(prefix, path):
  	if prefix in words:
  		yield (prefix, path)
  	for (nx, ny) in neighbors(path[-1]):
  		if (nx, ny) not in path:
  			prefix1 = prefix + grid[ny][nx]
  			if prefix1 in prefixes:
  				for result in extending(prefix1, path + ((nx, ny),)):
  					yield result
  
  
  def neighbors(xxx_todo_changeme):
  	(x, y) = xxx_todo_changeme
  	for nx in range(max(0, x - 1), min(x + 2, ncols)):
  		for ny in range(max(0, y - 1), min(y + 2, nrows)):
  			yield (nx, ny)
  
  
  # Print a maximal-length word and its path:
  # print(max(solve(), key=lambda word_path: len(word_path[0])))
  
  found_words = list(solve())
  for i in sorted(found_words, key=lambda word: len(word[0])):
  	print(i)
  