Skip to content

Instantly share code, notes, and snippets.

@ovs-code
Last active December 15, 2020 19:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ovs-code/25e810fb0818078cf9f9b08133b76334 to your computer and use it in GitHub Desktop.
Save ovs-code/25e810fb0818078cf9f9b08133b76334 to your computer and use it in GitHub Desktop.
# https://codegolf.stackexchange.com/questions/216361/can-the-statues-be-stacked
import re
import sys
from typing import List, TypeVar
T = TypeVar('T')
def all_indices(grid:List[List[T]], element:T):
for y, row in enumerate(grid):
for x, value in enumerate(row):
if value == element:
yield (x, y)
def solve(grid):
statues = []
base_idx = list(all_indices(grid, '-')) + list(all_indices(grid, '|'))
border_idx = list(all_indices(grid, '#'))
while base_idx:
(x, y), *base_idx = base_idx
base = [(x, y)]
if grid[y][x] == '-':
maxx = minx = x
while minx > 0 and grid[y][minx-1] == '-':
minx -= 1
base_idx.remove((minx, y))
base.append((minx, y))
while maxx+1 < len(grid[y]) and grid[y][maxx+1] == '-':
maxx += 1
base_idx.remove((maxx, y))
base.append((maxx, y))
else:
maxy = miny = y
while miny > 0 and grid[miny-1][x] == '|':
miny -= 1
base_idx.remove((x, miny))
base.append((x, miny))
while maxy+1 < len(grid) and grid[maxy+1][x] == '|':
maxy += 1
base_idx.remove((x, maxy))
base.append((x, maxy))
neighbors = base[:]
statue = []
while neighbors:
statue.extend(neighbors)
neighbors = [(bx, by) for bx, by in border_idx if any(abs(ax-bx)+abs(ay-by)==1 for ax, ay in neighbors)]
for n in neighbors:
border_idx.remove(n)
if grid[y][x] == '-':
heights = [abs(y-sy) for _, sy in statue]
else:
heights = [abs(x-sx) for sx, _ in statue]
base_width = len(base)
top_width = heights.count(max(heights))
statues.append((-base_width, -top_width))
return sorted(list(sum(statues, ()))) == list(sum(sorted(statues), ()))
def parse_tests(tests: str):
for test in re.split('\n\n_+\n\n', tests):
lines = test.splitlines()
width = max(len(line) for line in lines)
yield [list(line.ljust(width)) for line in lines]
if __name__ == '__main__':
for c in parse_tests(sys.stdin.read()):
print(solve(c))
Q=sorted
E=enumerate
def f(G):
s=[];B,S=[{(x,y)for y,r in E(G)for x,v in E(r)if v in e}for e in('-|','#')]
while B:
u,U=l,L=x,y=d=min(B);b={d};R=G[y];exec("l-='-'[:l]==R[l-1];u+=R[u+1:]>[]!=R[u+1]=='-';L-='|'[:L]==G[L-1][x];U+=G[U+1:]>[]!=G[U+1][x]>'-';b|={(l,y),(u,y),(x,L),(x,U)};"*len(G+R));B-=b;z=-len(b);h=[]
while b:b={h.append(abs([x-a,y-p][R[x]<'|']))or(a,p)for a,p in S if any(abs(c-a)+abs(d-p)<2for c,d in b)};S-=b
s+=(z,-h.count(max(h))),
return[*sum(Q(s),())]==Q(sum(s,()))
@ovs-code
Copy link
Author

@ovs-code
Copy link
Author

@ovs-code
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment