From 19a4a5cc6a925e3a4f954ce65ce08f955df4f5a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andy=20Teijelo=20P=C3=A9rez?= Date: Tue, 22 Nov 2016 07:44:11 -0500 Subject: [PATCH] Finished. Now comes extensive testing. --- main.py | 198 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 156 insertions(+), 42 deletions(-) diff --git a/main.py b/main.py index 514041a..153b084 100755 --- a/main.py +++ b/main.py @@ -89,18 +89,21 @@ def invariants(width, pattern, constraints=None): invs = [] for sol in solve2(width, pattern, constraints): exp = list(expand_solution(sol, width, pattern)) - count += 1 if len(invs) == 0: invs = exp else: for i, e in enumerate(exp): if invs[i] != e: invs[i] = -1 - return count, invs + return invs def visual(constraints): "returns a visual representation of constraints" - return "".join({1:'\N{LEFT SEVEN EIGHTHS BLOCK}', 0:'.', -1:'?'}[x] for x in constraints) + return "".join({ + 1:'\N{FULL BLOCK}\N{LEFT SEVEN EIGHTHS BLOCK}', + 0:'__', + -1:'??' + }[x] for x in constraints) class Board: """Board @@ -119,17 +122,17 @@ class Board: for i in range(self.height): self.rows[i] = [-1] * self.width - print("rows:") - for y in range(self.height): - n, c = invariants(self.width, self.row_patterns[y]) - print(n, self.row_patterns[y], visual(c)) + # print("rows:") + # for y in range(self.height): + # n, c = invariants(self.width, self.row_patterns[y]) + # print(n, self.row_patterns[y], visual(c)) - print("cols:") - for x in range(self.height): - n, c = invariants(self.width, self.col_patterns[x]) - print(n, self.col_patterns[x], visual(c)) + # print("cols:") + # for x in range(self.height): + # n, c = invariants(self.width, self.col_patterns[x]) + # print(n, self.col_patterns[x], visual(c)) - print(self.row(0)) + # print(self.row(0)) def col(self, i): """a column""" @@ -139,37 +142,121 @@ class Board: """a row""" return self.rows[i] - def solve(self): - min_row_index = 0 - min_row_count = 0 + def replace_row(self, i, row): + self.rows[i] = row + + def replace_col(self, i , col): for y in range(self.height): - count = 0 + self.rows[y][i] = col[y] + + + def compute_invariants(self): + while True: + changed = False + + row_sols = [0] * self.height + col_sols = [0] * self.width + + # rows + for y in range(self.height): + invs = None; count = 0 + for sol in solve2(self.width, self.row_patterns[y], self.row(y)): + count += 1 + exp = list(expand_solution(sol, self.width, self.row_patterns[y])) + if invs == None: + invs = exp + for i, e in enumerate(exp): + if invs[i] != e: + invs[i] = -1 + if invs != None and self.row(y) != invs: + self.replace_row(y, invs) + changed = True + row_sols[y] = count + + # columns + for x in range(self.width): + invs = None; count = 0 + for sol in solve2(self.height, self.col_patterns[x], self.col(x)): + count += 1 + exp = list(expand_solution(sol, self.height, self.col_patterns[x])) + if invs == None: + invs = exp + for i, e in enumerate(exp): + if invs[i] != e: + invs[i] = -1 + if invs != None and self.col(x) != invs: + self.replace_col(x, invs) + changed = True + col_sols[x] = count + + if not changed: + break + + return row_sols, col_sols + + def solve(self, solved=lambda x: None, depth=0): + row_sols, col_sols = self.compute_invariants() + # if depth < 2: + # print("depth:", depth) + # print(self) + # print("row_sols:", row_sols) + # print("col_sols:", col_sols) + + if min(row_sols) == 0 or min(col_sols) == 0: + return False + + if max(row_sols) == 1: + print("solved") + solved(self) + return True + + min_row, y = min((a,b) for b,a in enumerate(row_sols) if a > 1) + min_col, x = min((a,b) for b,a in enumerate(col_sols) if a > 1) + + if min_row < min_col: for sol in solve2(self.width, self.row_patterns[y], self.row(y)): - count += 1 - if count < min_row_count: - min_row_count = count - min_row_index = y + b = self.copy() + b.replace_row(y, expand_solution(sol, self.width, self.row_patterns[y])) + if b.solve(solved, depth + 1): + return True + else: + for sol in solve2(self.height, self.col_patterns[x], self.col(x)): + b = self.copy() + b.replace_col(x, expand_solution(sol, self.height, self.col_patterns[x])) + if b.solve(solved, depth + 1): + return True - pass + def copy(self): + newboard = Board((self.col_patterns, self.row_patterns)) + for i in range(self.height): + newboard.rows[i] = self.rows[i][:] + return newboard + + def __str__(self): + s = "" + for y in range(self.height): + s += visual(self.rows[y]) + s += "\n" + return s if __name__ == "__main__": def draw(solution, width, pattern): "draws a solution" for s, p in zip(solution, pattern): - print('.' * s, end="") - print('\N{LEFT SEVEN EIGHTHS BLOCK}' * p, end="") + print('__' * s, end="") + print('\N{FULL BLOCK}\N{LEFT SEVEN EIGHTHS BLOCK}' * p, end="") print('.' * (width - sum(solution) - sum(pattern))) - width = int(sys.argv[1]) - pattern = tuple(int(x) for x in sys.argv[2].split()) - constraints = [-1] * width - try: - for i, c in enumerate(sys.argv[3]): - constraints[i] = {'1':1, '0':0, '?':-1}[c] - except: - constraints = [-1] * width + # width = int(sys.argv[1]) + # pattern = tuple(int(x) for x in sys.argv[2].split()) + # constraints = [-1] * width + # try: + # for i, c in enumerate(sys.argv[3]): + # constraints[i] = {'1':1, '0':0, '?':-1}[c] + # except: + # constraints = [-1] * width # for solution in solve1(width, pattern): # e = expand_solution(solution, width, pattern) @@ -182,18 +269,45 @@ if __name__ == "__main__": rows = [[int(y) for y in x.strip().split()] for x in rows] return rows + def parse_constraints(s, width): + constraints = [-1] * width + for i, c in enumerate(s): + constraints[i] = {'1':1, '0':0, '?':-1, '.':0, '\N{LEFT SEVEN EIGHTHS BLOCK}': 1}[c] + return constraints - b = Board(( - parse("""1 1 1 1 1, 1 1 1, 1 1 1 1, 1 2, 1 1 1 1, 1 1 1, 1 1 1, - 3 1, 1 1, 1 2 6 1, 2 1, 2 3 1, 1 1, 1 1 3 1, 2 1 1"""), - parse("""1 2, 1 1 2, 2 1 1 1 1, 3 1, 1 1 1 1, 1 2 1, 1, 1 1 1 2, - 2 2 1 1, 1 1 1 1 1, 1 2 2, 2 2, 1 1 1 1 1, 1 1 1 1, 1 1""") - )) + # width = 15 + # pattern = (1, 1, 1, 2) + # constraints = parse_constraints('????????010?', width) + # for sol in solve2(width, pattern, constraints): + # draw(sol, width, pattern) - # c = Board(( - # parse("""1 5 2, 1 1 2, 1 1 2 1 2, 2 2, 2 1 1 1, 1 1 1, 1 1, 1 1 1, 2 3 1 1, - # 1 2 3 1 1, 1 3 1 1, 2 1 1 1, 1 1 1 2 1, 1 1 1 2 1, 2 1"""), - # parse("""1 2 1 1, 1 1 4, 2 1, 1 1 1 1 2, 1 3 1 1, 1 2, 1 1 1 1 1 1, - # 1 1 1 1 1 2, 1 1 2, 1 2 1 1, 3 1 4, 1 4 1, 3, 3 1 1, 1 2 1""") + # b = Board(( + # parse("1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1"), + # parse("1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1") # )) + # b.solve(print) + + # b = Board(( + # parse("""1 1 1 1 1, 1 1 1, 1 1 1 1, 1 2, 1 1 1 1, 1 1 1, 1 1 1, + # 3 1, 1 1, 1 2 6 1, 2 1, 2 3 1, 1 1, 1 1 3 1, 2 1 1"""), + # parse("""1 2, 1 1 2, 2 1 1 1 1, 3 1, 1 1 1 1, 1 2 1, 1, 1 1 1 2, + # 2 2 1 1, 1 1 1 1 1, 1 2 2, 2 2, 1 1 1 1 1, 1 1 1 1, 1 1""") + # )) + # b.solve(print) + + # b = Board(( + # parse("""2 4, 1 1 3 1, 6, 3 3, 3 4, 1 3 2, 3 4 1, 3 5 1 1, 12, + # 5 3 3, 6 4, 2 3, 1 2 2, 3 4, 3 5"""), + # parse("""1 6, 2 2 4 2, 3 5 2, 11, 1 6 1, 4 1 5, 5 3 3, 10 2, 1 7 1 1, 5 1 1 1, + # 1 3 1, 3, 3, 1 1, 3"""), + # )) + # b.solve() + + c = Board(( + parse("""1 5 2, 1 1 2, 1 1 2 1 2, 2 2, 2 1 1 1, 1 1 1, 1 1, 1 1 1, 2 3 1 1, + 1 2 3 1 1, 1 3 1 1, 2 1 1 1, 1 1 1 2 1, 1 1 1 2 1, 2 1"""), + parse("""1 2 1 1, 1 1 4, 2 1, 1 1 1 1 2, 1 3 1 1, 1 2, 1 1 1 1 1 1, + 1 1 1 1 1 2, 1 1 2, 1 2 1 1, 3 1 4, 1 4 1, 3, 3 1 1, 1 2 1""") + )) + c.solve(print)