You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
4.6 KiB
Python
154 lines
4.6 KiB
Python
#!/usr/bin/python
|
|
from constraint import *
|
|
import random
|
|
import sys
|
|
|
|
MINLEN = 3
|
|
|
|
def main(puzzle, lines):
|
|
puzzle = puzzle.rstrip().splitlines()
|
|
while puzzle and not puzzle[0]:
|
|
del puzzle[0]
|
|
|
|
# Extract horizontal words
|
|
horizontal = []
|
|
word = []
|
|
predefined = {}
|
|
for row in range(len(puzzle)):
|
|
for col in range(len(puzzle[row])):
|
|
char = puzzle[row][col]
|
|
if not char.isspace():
|
|
word.append((row, col))
|
|
if char != "#":
|
|
predefined[row, col] = char
|
|
elif word:
|
|
if len(word) > MINLEN:
|
|
horizontal.append(word[:])
|
|
del word[:]
|
|
if word:
|
|
if len(word) > MINLEN:
|
|
horizontal.append(word[:])
|
|
del word[:]
|
|
|
|
# Extract vertical words
|
|
vertical = []
|
|
validcol = True
|
|
col = 0
|
|
while validcol:
|
|
validcol = False
|
|
for row in range(len(puzzle)):
|
|
if col >= len(puzzle[row]):
|
|
if word:
|
|
if len(word) > MINLEN:
|
|
vertical.append(word[:])
|
|
del word[:]
|
|
else:
|
|
validcol = True
|
|
char = puzzle[row][col]
|
|
if not char.isspace():
|
|
word.append((row, col))
|
|
if char != "#":
|
|
predefined[row, col] = char
|
|
elif word:
|
|
if len(word) > MINLEN:
|
|
vertical.append(word[:])
|
|
del word[:]
|
|
if word:
|
|
if len(word) > MINLEN:
|
|
vertical.append(word[:])
|
|
del word[:]
|
|
col += 1
|
|
|
|
hnames = ["h%d" % i for i in range(len(horizontal))]
|
|
vnames = ["v%d" % i for i in range(len(vertical))]
|
|
|
|
#problem = Problem(MinConflictsSolver())
|
|
problem = Problem()
|
|
|
|
for hi, hword in enumerate(horizontal):
|
|
for vi, vword in enumerate(vertical):
|
|
for hchar in hword:
|
|
if hchar in vword:
|
|
hci = hword.index(hchar)
|
|
vci = vword.index(hchar)
|
|
problem.addConstraint(lambda hw, vw, hci=hci, vci=vci:
|
|
hw[hci] == vw[vci],
|
|
("h%d" % hi, "v%d" % vi))
|
|
|
|
for char, letter in predefined.items():
|
|
for hi, hword in enumerate(horizontal):
|
|
if char in hword:
|
|
hci = hword.index(char)
|
|
problem.addConstraint(lambda hw, hci=hci, letter=letter:
|
|
hw[hci] == letter, ("h%d" % hi,))
|
|
for vi, vword in enumerate(vertical):
|
|
if char in vword:
|
|
vci = vword.index(char)
|
|
problem.addConstraint(lambda vw, vci=vci, letter=letter:
|
|
vw[vci] == letter, ("v%d" % vi,))
|
|
|
|
wordsbylen = {}
|
|
for hword in horizontal:
|
|
wordsbylen[len(hword)] = []
|
|
for vword in vertical:
|
|
wordsbylen[len(vword)] = []
|
|
|
|
for line in lines:
|
|
line = line.strip()
|
|
l = len(line)
|
|
if l in wordsbylen:
|
|
wordsbylen[l].append(line.upper())
|
|
|
|
for hi, hword in enumerate(horizontal):
|
|
words = wordsbylen[len(hword)]
|
|
random.shuffle(words)
|
|
problem.addVariable("h%d" % hi, words)
|
|
for vi, vword in enumerate(vertical):
|
|
words = wordsbylen[len(vword)]
|
|
random.shuffle(words)
|
|
problem.addVariable("v%d" % vi, words)
|
|
|
|
problem.addConstraint(AllDifferentConstraint())
|
|
|
|
solution = problem.getSolution()
|
|
if not solution:
|
|
print "No solution found!"
|
|
|
|
maxcol = 0
|
|
maxrow = 0
|
|
for hword in horizontal:
|
|
for row, col in hword:
|
|
if row > maxrow:
|
|
maxrow = row
|
|
if col > maxcol:
|
|
maxcol = col
|
|
for vword in vertical:
|
|
for row, col in vword:
|
|
if row > maxrow:
|
|
maxrow = row
|
|
if col > maxcol:
|
|
maxcol = col
|
|
|
|
matrix = []
|
|
for row in range(maxrow+1):
|
|
matrix.append([" "]*(maxcol+1))
|
|
|
|
for variable in solution:
|
|
if variable[0] == "v":
|
|
word = vertical[int(variable[1:])]
|
|
else:
|
|
word = horizontal[int(variable[1:])]
|
|
for (row, col), char in zip(word, solution[variable]):
|
|
matrix[row][col] = char
|
|
|
|
for row in range(maxrow+1):
|
|
for col in range(maxcol+1):
|
|
sys.stdout.write(matrix[row][col])
|
|
sys.stdout.write("\n")
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 3:
|
|
sys.exit("Usage: crosswords.py <maskfile> <wordsfile>")
|
|
main(open(sys.argv[1]).read(), open(sys.argv[2]))
|
|
|