Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
may the force be with you solution in Clear category for Unruly by juestr
from functools import reduce
from itertools import permutations
def unruly(grid):
rows, cols = len(grid), len(grid[0])
rows_and_cols = [(r, None) for r in range(rows)] + [(None, c) for c in range(cols)]
def constrain(cell1, cell2):
return cell1 if cell1 == cell2 else '.'
def seq_check(seq):
return all(color*3 not in seq and seq.count(color) <= len(seq) // 2 for color in 'BW')
def seq_all_fills(seq, b, w):
def fill(xs):
stack = list(xs)
return ''.join(stack.pop() if cell == '.' else cell for cell in seq)
return [fill(f) for f in set(permutations('B'*b + 'W'*w))]
def grid_get(grid, r=None, c=None):
if c is None:
return grid[r]
elif r is None:
return ''.join(row[c] for row in grid)
else:
return grid[r][c]
def grid_set(grid, r, c, val):
if c is None:
return grid[:r] + (val,) + grid[r+1:]
elif r is None:
return tuple(row[:c] + v + row[c+1:] for row, v in zip(grid, val))
else:
return tuple(row[:c] + val + row[c+1:] if r == y else row for y, row in enumerate(grid))
def grid_undecided(grid):
return ((r, c) for r, row in enumerate(grid) for c, cell in enumerate(row) if cell == '.')
def grid_check(grid, r=None, c=None, val=None):
if val is not None:
grid = grid_set(grid, r, c, val)
return all(seq_check(grid_get(grid, r=y)) for y in (range(rows) if r is None else (r,))) and \
all(seq_check(grid_get(grid, c=x)) for x in (range(cols) if c is None else (c,)))
def force_cell(grid_progress, r_c):
grid, _ = grid_progress
new_grids = (grid_set(grid, *r_c, color) for color in 'BW')
valid_grids = [new for new in new_grids if grid_check(new, *r_c)]
return (valid_grids[0], True) if len(valid_grids) == 1 else grid_progress
def force_line(grid_progress, r_c):
grid, _ = grid_progress
seq = grid_get(grid, *r_c)
nB, nW, cap = seq.count('B'), seq.count('W'), len(seq) // 2
if (nB == cap - 1) or (nW == cap - 1):
valid_seqs = (s for s in seq_all_fills(seq, cap-nB, cap-nW) if grid_check(grid, *r_c, s))
forced = ''.join(reduce(constrain, transposed) for transposed in zip(*valid_seqs))
if seq != forced:
return grid_set(grid, *r_c, forced), True
return grid_progress
while(True):
grid, progress = reduce(force_cell, grid_undecided(grid), (grid, False))
grid, progress = reduce(force_line, rows_and_cols, (grid, progress))
if not progress:
return grid
Feb. 3, 2020
Comments: