Solve a row with constraints

This commit is contained in:
Andy Teijelo Pérez 2016-11-20 23:54:36 -05:00
parent 4f44c1442a
commit a4d3ac9247

58
main.py
View file

@ -3,13 +3,12 @@
from itertools import combinations_with_replacement from itertools import combinations_with_replacement
def row_solutions(width, pattern): def solve1(width, pattern):
""" """
This yields a tuple for each possible layout of This yields a tuple for each possible layout of
pattern inside the row. The tuple elements are the pattern inside the row. The tuple elements are the
amount of cells that must be inserted before each gaps before each block in pattern.
block in pattern. The tuple doesn't include the The tuple doesn't include the last gap, since that's
number of cells at the end of the row since that's
just: width - sum(sol) - sum(pattern) just: width - sum(sol) - sum(pattern)
""" """
spaces = width - (sum(pattern) + len(pattern) - 1) spaces = width - (sum(pattern) + len(pattern) - 1)
@ -31,7 +30,7 @@ def expand_solution(solution, width, pattern):
def matches(expanded_solution, constraints): def matches(expanded_solution, constraints):
""" """
solution is a tuple of spaces, the output of row_solutions solution is a tuple of spaces, the output of solve1
constraints is a tuple of values from 1, 0 and -1, that constraints is a tuple of values from 1, 0 and -1, that
mean: mean:
0 -> OFF 0 -> OFF
@ -46,6 +45,41 @@ def matches(expanded_solution, constraints):
return True return True
def solve2(width, pattern, constraints=None):
"""
@width: int
@pattern: sequence of ints
@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
"""
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
maxgap = width - sum(pattern[1:]) - (len(pattern) - 1) - p
for gap in range(maxgap + 1):
e = expand_solution((gap,), gap + p + 1, (p,))
if not matches(e, constraints[:gap + p + 1]):
continue
if len(pattern) == 1:
yield (gap,)
continue
subwidth = width - gap - p - 1
subpattern = pattern[1:]
subconstraints = constraints[-subwidth:]
for s in solve2(subwidth, subpattern, subconstraints):
yield (gap,s[0]+1) + s[1:]
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
@ -53,7 +87,7 @@ if __name__ == "__main__":
def draw(solution, width, pattern): def draw(solution, width, pattern):
for s,p in zip(solution, pattern): for s,p in zip(solution, pattern):
print('.' * s, end="") print('.' * s, end="")
print('\N{FULL BLOCK}' * p, end="") print('\N{LEFT SEVEN EIGHTHS BLOCK}' * p, end="")
print('.' * (width - sum(solution) - sum(pattern))) print('.' * (width - sum(solution) - sum(pattern)))
width = int(sys.argv[1]) width = int(sys.argv[1])
@ -63,10 +97,12 @@ if __name__ == "__main__":
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:
print(sys.exc_info())
constraints = [-1] * width constraints = [-1] * width
for solution in row_solutions(width, pattern): # for solution in solve1(width, pattern):
e = expand_solution(solution, width, pattern) # e = expand_solution(solution, width, pattern)
if matches(e, constraints): # if matches(e, constraints):
draw(solution, width, pattern) # draw(solution, width, pattern)
for sol in solve2(width, pattern, constraints):
draw(sol, width, pattern)