Compare commits

..

No commits in common. "a2fa29ab4b9e9c6ef95d2fbc7a2c8a9ec87d6808" and "70ac0f773fe8cbc9d6b0bb539fd45938c8fc9883" have entirely different histories.

126
main.py
View file

@ -1,9 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"This module does something"
from itertools import combinations_with_replacement from itertools import combinations_with_replacement
import sys
def solve1(width, pattern): def solve1(width, pattern):
@ -16,7 +13,7 @@ def solve1(width, pattern):
""" """
spaces = width - (sum(pattern) + len(pattern) - 1) spaces = width - (sum(pattern) + len(pattern) - 1)
for sol in combinations_with_replacement(range(spaces + 1), len(pattern)): 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 yield sol
def expand_solution(solution, width, pattern): def expand_solution(solution, width, pattern):
@ -24,7 +21,7 @@ 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 = [] r = []
for s, p in zip(solution, pattern): for s,p in zip(solution, pattern):
r.extend([0] * s) r.extend([0] * s)
r.extend([1] * p) r.extend([1] * p)
r.extend([0] * (width - sum(solution) - sum(pattern))) r.extend([0] * (width - sum(solution) - sum(pattern)))
@ -40,7 +37,7 @@ def matches(expanded_solution, constraints):
1 -> ON 1 -> ON
-1 -> not constrained -1 -> not constrained
""" """
for s, c in zip(expanded_solution, constraints): for s,c in zip(expanded_solution, constraints):
if c == -1: if c == -1:
continue continue
if c != s: if c != s:
@ -70,10 +67,8 @@ def solve2(width, pattern, constraints=None):
maxgap = width - sum(pattern[1:]) - (len(pattern) - 1) - p maxgap = width - sum(pattern[1:]) - (len(pattern) - 1) - p
for gap in range(maxgap + 1): for gap in range(maxgap + 1):
# constraint width e = expand_solution((gap,), gap + p + 1, (p,))
cw = (gap + p + 1) if len(pattern) > 1 else width if not matches(e, constraints[:gap + p + 1]):
e = expand_solution((gap,), cw, (p,))
if not matches(e, constraints[:cw]):
continue continue
if len(pattern) == 1: if len(pattern) == 1:
yield (gap,) yield (gap,)
@ -82,82 +77,15 @@ def solve2(width, pattern, constraints=None):
subpattern = pattern[1:] subpattern = pattern[1:]
subconstraints = constraints[-subwidth:] subconstraints = constraints[-subwidth:]
for s in solve2(subwidth, subpattern, subconstraints): 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__": if __name__ == "__main__":
import sys
def draw(solution, width, pattern): def draw(solution, width, pattern):
"draws a solution" for s,p in zip(solution, pattern):
for s, p in zip(solution, pattern):
print('.' * s, end="") print('.' * s, end="")
print('\N{LEFT SEVEN EIGHTHS BLOCK}' * p, end="") print('\N{LEFT SEVEN EIGHTHS BLOCK}' * p, end="")
print('.' * (width - sum(solution) - sum(pattern))) print('.' * (width - sum(solution) - sum(pattern)))
@ -166,8 +94,8 @@ if __name__ == "__main__":
pattern = tuple(int(x) for x in sys.argv[2].split()) pattern = tuple(int(x) for x in sys.argv[2].split())
constraints = [-1] * width constraints = [-1] * width
try: try:
for i, c in enumerate(sys.argv[3]): for i,c in enumerate(sys.argv[3]):
constraints[i] = {'1':1, '0':0, '?':-1}[c] constraints[i]= {'1':1, '0':0, '?':-1}[c]
except: except:
constraints = [-1] * width constraints = [-1] * width
@ -176,24 +104,16 @@ if __name__ == "__main__":
# if matches(e, constraints): # if matches(e, constraints):
# draw(solution, width, pattern) # draw(solution, width, pattern)
def parse(rows): fixed = []
"parses '1 1, 1 2 3' into [[1, 1], [1, 2, 3]]" for sol in solve2(width, pattern, constraints):
rows = rows.split(",") exp = list(expand_solution(sol, width, pattern))
rows = [[int(y) for y in x.strip().split()] for x in rows] if len(fixed) == 0:
return rows fixed = exp
else:
for i,e in enumerate(exp):
b = Board(( if fixed[i] != e:
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, fixed[i] = -1
3 1, 1 1, 1 2 6 1, 2 1, 2 3 1, 1 1, 1 1 3 1, 2 1 1"""), draw(sol, width, pattern)
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))