#!/usr/bin/env python3 from itertools import combinations_with_replacement def row_solutions(width, pattern): """ This yields a tuple for each possible layout of pattern inside the row. The tuple elements are the amount of cells that must be inserted before each block in pattern. The tuple doesn't include the number of cells at the end of the row since that's 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))) yield sol def expand_solution(solution, width, pattern): """ expands a solution to a tuple of 1 (ON) and 0 (OFF) """ r = [] for s,p in zip(solution, pattern): r.extend([0] * s) r.extend([1] * p) r.extend([0] * (width - sum(solution) - sum(pattern))) return tuple(r) def matches(expanded_solution, constraints): """ solution is a tuple of spaces, the output of row_solutions constraints is a tuple of values from 1, 0 and -1, that mean: 0 -> OFF 1 -> ON -1 -> not constrained """ for s,c in zip(expanded_solution, constraints): if c == -1: continue if c != s: return False return True if __name__ == "__main__": import sys def draw(solution, width, pattern): for s,p in zip(solution, pattern): print('.' * s, end="") print('\N{FULL 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: print(sys.exc_info()) constraints = [-1] * width for solution in row_solutions(width, pattern): e = expand_solution(solution, width, pattern) if matches(e, constraints): draw(solution, width, pattern)