You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1 anno fa
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. @lambda fn: lambda brick: set(fn(brick))
  2. def dimension(brick):
  3. (x1, x2), (y1, y2), (z1, z2) = map(sorted, zip(*brick))
  4. for z in range(z1, z2 + 1):
  5. for y in range(y1, y2 + 1):
  6. for x in range(x1, x2 + 1):
  7. yield x, y, z
  8. def tetris(bricks):
  9. floor = {(x, y, 0) for x in range(100) for y in range(100)}
  10. seen = floor
  11. for brick in map(dimension, bricks):
  12. while not seen & brick:
  13. brick = {(x, y, z - 1) for x, y, z in brick}
  14. resting_place = {(x, y, z + 1) for x, y, z in brick}
  15. seen |= resting_place
  16. yield resting_place
  17. def topple(i, depends_on, holds_up):
  18. gone = set()
  19. state = {i}
  20. while state:
  21. gone |= state
  22. state = {above
  23. for below in state
  24. for above in depends_on.get(below, [])
  25. if holds_up[above] <= gone
  26. }
  27. return gone - {i}
  28. text = open(0).read()
  29. bricks = [[[int(n) for n in sub.split(',')] for sub in line.split('~')] for line in text.splitlines()]
  30. bricks.sort(key=lambda brick: min(z for x, y, z in brick))
  31. bricks = list(tetris(bricks))
  32. known = {i for i, _ in enumerate(bricks)}
  33. holds_up, depends_on = {}, {}
  34. for j, brick in enumerate(bricks):
  35. j_brick_1_down = {(x, y, z - 1) for x, y, z in brick}
  36. holds_up[j] = {i for i, i_brick in enumerate(bricks) if i != j and j_brick_1_down & i_brick}
  37. for i in holds_up[j]:
  38. depends_on.setdefault(i, set()).add(j)
  39. needed = {v for k, vs in holds_up.items() if len(vs) == 1 for v in vs}
  40. print(len(known - needed))
  41. print(sum(len(topple(i, depends_on, holds_up)) for i in needed))