9.19
Idea
A word (or Babbage) square is a list of [math]k[/math]-letter words
S = (w0, … , wk-1) such that ∀ i,j : wi[j] = wj[i].
Fixing the first word to the given word [math]w[/math] turns the search into a constrained back-tracking problem.
Prefix table
To prune early, store every dictionary word of length [math]k[/math] in a map
prefixes[p] → list of words that start with string p (Trie or defaultdict(list)).
Only those words that match the current column prefixes are considered in each step.
Recursive procedure
Let square
be the current list of rows (initially [ w
]).
Current depth d = len(square).
Required prefix for the next row = column d formed so far:
prefix = ''.join(square[i][d] for i in range(d)).
For every candidate word in prefixes[prefix]:
append it to square
, recurse; on return pop it out.
When d = k the square is complete – emit a copy.
Complexities
Building the prefix table: O(n·k).
Search: O(S·k²) where S is the number of squares produced (each validity check takes O(k)).
Reference Python 3 implementation
Usage example
The function returns the two squares shown in the statement and any other squares that begin with the same first row.
Back to
Chapter 9