record brick [ x1 y1 z1 : int; x2 y2 z2 : int; ] implicit fn instance_ord_brick~inline : class_ord(brick) := class_ord(brick).[ equal : lambda(a b : brick) [ return a.z1 = b.z1; ], less : lambda(a b : brick) [ return a.z1 < b.z1; ], ]; fn try_to_fall(occupied : list(list(list(bool))), b : brick) : int [ var f := 0; while true do [ for x := b.x1 to b.x2 + 1 do [ for y := b.y1 to b.y2 + 1 do [ if occupied[b.z1 - 1][y][x] then return f; ] ] f += 1; b.z1 -= 1; b.z2 -= 1; ] abort; ] fn set_occupied(occupied : list(list(list(bool))), b : brick, state : bool) : list(list(list(bool))) [ for x := b.x1 to b.x2 + 1 do [ for y := b.y1 to b.y2 + 1 do [ occupied[b.z2][y][x] := state; ] ] return occupied; ] fn main [ var lines := list_break_to_lines(read_lazy(h[0])); var bricks := empty(brick); for line in lines do [ line := list_replace_substring(line, "~", ","); var c := map(list_break(line, ','), ston); var b := brick.[ x1 : c[0], y1 : c[1], z1 : c[2], x2 : c[3], y2 : c[4], z2 : c[5] ]; bricks +<= b; ] bricks := list_sort(bricks); var occupied := infinite(infinite(infinite(false))); occupied[0] := infinite(infinite(true)); for a := 0 to len(bricks) do [ var f := try_to_fall(occupied, bricks[a]); bricks[a].z1 -= f; bricks[a].z2 -= f; occupied := set_occupied(occupied, bricks[a], true); ] var sum := 0; for a := 0 to len(bricks) do [ var uo := set_occupied(occupied, bricks[a], false); for b := 0 to len(bricks) do [ if bricks[b].z1 = bricks[a].z2 + 1 then [ var f := try_to_fall(uo, bricks[b]); if f > 0 then goto cant_disintegrate; ] ] sum += 1; cant_disintegrate: ] write(h[1], ntos(sum) + nl); ]