-
Notifications
You must be signed in to change notification settings - Fork 0
/
solver.py
106 lines (82 loc) · 3 KB
/
solver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env python3
import os
import sys
UNKNOWN, FREE, FILLED = range(3)
class Nonogramm:
def __init__(self, width, height, rows, cols):
self.width = width
self.height = height
self.rows = tuple(tuple(x) for x in rows)
self.cols = tuple(tuple(x) for x in cols)
self.grid = [[UNKNOWN]*height for _ in range(width)]
self.dimensions = (width, height)
def __get(self, axis, line_index, cell_index):
if axis == 0:
return self.grid[line_index][cell_index]
return self.grid[cell_index][line_index]
def __set(self, axis, line_index, cell_index, value):
if axis == 0:
self.grid[line_index][cell_index] = value
else:
self.grid[cell_index][line_index] = value
def __prefill(self, axis, line_index):
hints = (self.cols if axis == 0 else self.rows)[line_index]
space = self.dimensions[1 - axis] - sum(hints) - len(hints) + 1
if space < max(hints):
total = 0
for hint in hints:
if hint > space:
for i in range(total+space, total+hint):
self.__set(axis, line_index, i, FILLED)
total += hint + 1
def solve(self):
for x in range(self.width):
self.__prefill(0, x)
for y in range(self.height):
self.__prefill(1, y)
def print_grid(self):
for y in range(self.height):
for x in range(self.width):
print((".", "X", "#")[self.grid[x][y]], end="")
print()
@staticmethod
def from_file(filename):
index = -1
rows = []
cols = []
with open(filename) as f:
try:
for line in f:
line = line.strip()
if not line or line[0] == "#":
continue
if index < 0:
width, height = map(int, line.split(" "))
elif index < height:
rows.append([int(x) for x in line.split(" ")])
elif index < height + width:
cols.append([int(x) for x in line.split(" ")])
else:
break
index += 1
except ValueError:
return None
if len(rows) != height or len(cols) != width:
return None
return Nonogramm(width, height, rows, cols)
def main():
if len(sys.argv) != 2 or sys.argv[1] in ("-h", "help"):
print("Usage:", sys.argv[0], "NONOGRAMM-FILE")
exit(1)
elif not os.path.isfile(sys.argv[1]):
print("'{}' is not a valid file".format(sys.argv[1]))
exit(1)
nonogramm = Nonogramm.from_file(sys.argv[1])
if nonogramm is None:
print("'{}' doesn't contain a valid nonogramm".format(sys.argv[1]))
exit(2)
print("Solving...")
nonogramm.solve()
nonogramm.print_grid()
if __name__ == "__main__":
main()