Download
"""
PyCSP3 Model (see pycsp.org)
Data can come:
- either directly from a JSON file
- or from an intermediate parser
Examples:
python Nonogram.py -data=Nonogram_example.json
python Nonogram.py -data=Nonogram_example.json -variant=table
python Nonogram.py -data=Nonogram_example.txt -dataparser=Nonogram_Parser.py
"""
from pycsp3 import *
rows, cols = data # patterns for row and columns
nRows, nCols = len(rows), len(cols)
# x[i][j] is 1 iff the cell at row i and col j is colored in black
x = VarArray(size=[nRows, nCols], dom={0, 1})
if not variant():
def automaton(pattern):
q = Automaton.q # for building state names
transitions = []
if len(pattern) == 0:
n_states = 1
transitions.append((q(0), 0, q(0)))
else:
n_states = sum(pattern) + len(pattern)
num = 0
for i, size in enumerate(pattern):
transitions.append((q(num), 0, q(num)))
transitions.extend((q(num + j), 1, q(num + j + 1)) for j in range(size))
transitions.append((q(num + size), 0, q(num + size + (1 if i < len(pattern) - 1 else 0))))
num += size + 1
return Automaton(start=q(0), final=q(n_states - 1), transitions=transitions)
satisfy(
[x[i] in automaton(rows[i]) for i in range(nRows)],
[x[:, j] in automaton(cols[j]) for j in range(nCols)]
)
elif variant("table"):
cache = dict()
def table(pattern, row):
def build_from(lst, tmp, i, k):
s = sum([pattern[e] for e in range(k, len(pattern))])
if i + s + (len(pattern) - 1 - k) > len(tmp):
return lst
if i == len(tmp):
lst.append(tuple(tmp))
else:
tmp[i] = 0
build_from(lst, tmp, i + 1, k)
if k < len(pattern):
for j in range(i, i + pattern[k]):
tmp[j] = 1
if i + pattern[k] == len(tmp):
build_from(lst, tmp, i + pattern[k], k + 1)
else:
tmp[i + pattern[k]] = 0
build_from(lst, tmp, i + pattern[k] + 1, k + 1)
return lst
key = str("R" if row else "C") + "".join(str(pattern))
if key not in cache:
cache[key] = build_from([], [0] * (nCols if row else nRows), 0, 0)
return cache[key]
satisfy(
[x[i] in table(rows[i], row=True) for i in range(nRows)],
[x[:, j] in table(cols[j], row=False) for j in range(nCols)]
)