Compare commits
No commits in common. "a2fa29ab4b9e9c6ef95d2fbc7a2c8a9ec87d6808" and "70ac0f773fe8cbc9d6b0bb539fd45938c8fc9883" have entirely different histories.
a2fa29ab4b
...
70ac0f773f
1 changed files with 29 additions and 109 deletions
138
main.py
138
main.py
|
@ -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):
|
||||||
|
@ -12,19 +9,19 @@ def solve1(width, pattern):
|
||||||
pattern inside the row. The tuple elements are the
|
pattern inside the row. The tuple elements are the
|
||||||
gaps before each block in pattern.
|
gaps before each block in pattern.
|
||||||
The tuple doesn't include the last gap, since that's
|
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)
|
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):
|
||||||
"""
|
"""
|
||||||
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:
|
||||||
|
@ -55,109 +52,40 @@ def solve2(width, pattern, constraints=None):
|
||||||
@constraints: optional list of length width containing 1,0,-1 as elements
|
@constraints: optional list of length width containing 1,0,-1 as elements
|
||||||
|
|
||||||
Does the same as solve1, but takes constraints
|
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:
|
if len(pattern) == 0:
|
||||||
return tuple()
|
return tuple()
|
||||||
|
|
||||||
if constraints is None:
|
if constraints is None:
|
||||||
constraints = [-1] * width
|
constraints = [-1] * width
|
||||||
|
|
||||||
p = pattern[0]
|
p = pattern[0]
|
||||||
|
|
||||||
# the first gap can go from 0 to the following, inclusive
|
# the first gap can go from 0 to the following, inclusive
|
||||||
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,)
|
||||||
continue
|
continue
|
||||||
subwidth = width - gap - p - 1
|
subwidth = width - gap - p - 1
|
||||||
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))
|
||||||
|
|
Loading…
Reference in a new issue