diff --git a/main.py b/main.py index 7e068c4..0986840 100755 --- a/main.py +++ b/main.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +"This module does something" + from itertools import combinations_with_replacement +import sys def solve1(width, pattern): @@ -9,19 +12,19 @@ def solve1(width, pattern): pattern inside the row. The tuple elements are the gaps before each block in pattern. The tuple doesn't include the last gap, since that's - just: width - sum(sol) - sum(pattern) + just: width - sum(sol) - sum(pattern) """ spaces = width - (sum(pattern) + len(pattern) - 1) for sol in combinations_with_replacement(range(spaces + 1), len(pattern)): - sol = sol[0:1] + tuple((sol[i] - sol[i-1] + 1) for i in range(1,len(sol))) + sol = sol[0:1] + tuple((sol[i] - sol[i-1] + 1) for i in range(1, len(sol))) yield sol def expand_solution(solution, width, pattern): """ - expands a solution to a tuple of 1 (ON) and 0 (OFF) + expands a solution to a tuple of 1 (ON) and 0 (OFF) """ r = [] - for s,p in zip(solution, pattern): + for s, p in zip(solution, pattern): r.extend([0] * s) r.extend([1] * p) r.extend([0] * (width - sum(solution) - sum(pattern))) @@ -37,7 +40,7 @@ def matches(expanded_solution, constraints): 1 -> ON -1 -> not constrained """ - for s,c in zip(expanded_solution, constraints): + for s, c in zip(expanded_solution, constraints): if c == -1: continue if c != s: @@ -52,15 +55,15 @@ def solve2(width, pattern, constraints=None): @constraints: optional list of length width containing 1,0,-1 as elements Does the same as solve1, but takes constraints - in consideration to be faster than solve1 + matches + in consideration to be faster than solve1 + matches """ - + if len(pattern) == 0: return tuple() if constraints is None: constraints = [-1] * width - + p = pattern[0] # the first gap can go from 0 to the following, inclusive @@ -75,17 +78,84 @@ def solve2(width, pattern, constraints=None): continue subwidth = width - gap - p - 1 subpattern = pattern[1:] - subconstraints = constraints[-subwidth:] + subconstraints = constraints[-subwidth:] for s in solve2(subwidth, subpattern, subconstraints): - yield (gap,s[0]+1) + s[1:] + yield (gap, s[0]+1) + s[1:] +def invariants(width, pattern, constraints=None): + "compute invariants" + 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 + +def visual(constraints): + "returns a visual representation of constraints" + return "".join({1:'\N{LEFT SEVEN EIGHTHS BLOCK}', 0:'.', -1:'?'}[x] for x in constraints) + +class Board: + """Board + + A board is actually a list of constraints. + A cell with 1 or 0 is fixed. A cell with -1 + doesn't have a known value yet. + """ + + def __init__(self, patterns): + self.col_patterns = patterns[0] + self.row_patterns = patterns[1] + self.width = len(patterns[0]) + self.height = len(patterns[1]) + self.rows = [None] * self.height + 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("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)) + + def col(self, i): + """a column""" + return [self.rows[x][i] for x in range(self.height)] + + def row(self, i): + """a row""" + return self.rows[i] + + def solve(self): + min_row_index = 0 + min_row_count = 0 + for y in range(self.height): + count = 0 + 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 + + + pass if __name__ == "__main__": - - import sys def draw(solution, width, pattern): - for s,p in zip(solution, pattern): + "draws a solution" + for s, p in zip(solution, pattern): print('.' * s, end="") print('\N{LEFT SEVEN EIGHTHS BLOCK}' * p, end="") print('.' * (width - sum(solution) - sum(pattern))) @@ -94,8 +164,8 @@ if __name__ == "__main__": 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] + for i, c in enumerate(sys.argv[3]): + constraints[i] = {'1':1, '0':0, '?':-1}[c] except: constraints = [-1] * width @@ -104,16 +174,24 @@ if __name__ == "__main__": # if matches(e, constraints): # draw(solution, width, pattern) - fixed = [] - for sol in solve2(width, pattern, constraints): - exp = list(expand_solution(sol, width, pattern)) - if len(fixed) == 0: - fixed = exp - else: - for i,e in enumerate(exp): - if fixed[i] != e: - fixed[i] = -1 - draw(sol, width, pattern) + def parse(rows): + "parses '1 1, 1 2 3' into [[1, 1], [1, 2, 3]]" + rows = rows.split(",") + rows = [[int(y) for y in x.strip().split()] for x in rows] + return rows + + + 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""") + )) + + # 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""") + # )) - print("invariants:") - print("".join({1:'\N{LEFT SEVEN EIGHTHS BLOCK}',0:'.',-1:'?'}[x] for x in fixed))