#!/usr/bin/env python3 import sys,re from collections import Counter def parse(l): return re.compile(r"(?P\w+) x=(?P-?\d+)..(?P-?\d+),y=(?P-?\d+)..(?P-?\d+),z=(?P-?\d+)..(?P-?\d+)").search(l) def volume(k): if k[1]-k[0] < 0 or k[3]-k[2] < 0 or k[5]-k[4] < 0: return 0 return (k[1]-k[0]+1)*(k[3]-k[2]+1)*(k[5]-k[4]+1) def count_cubes(c): o = 0 for k,v in c.items(): if v == 'on': o += volume(k) return o def intersect(c1,c2): x1,x2,y1,y2,z1,z2 = c1 lx,hx,ly,hy,lz,hz = c2 xos = max(lx,x1) xoe = min(hx,x2) yos = max(ly,y1) yoe = min(hy,y2) zos = max(lz,z1) zoe = min(hz,z2) return volume((xos,xoe,yos,yoe,zos,zoe)) > 0 #return (c1[0] in range(c2[0],c2[1]+1) or c1[1] in range(c2[0],c2[1]+1)) and (c1[2] in range(c2[2],c2[3]+1) or c1[3] in range(c2[2],c2[3]+1)) and (c1[4] in range(c2[4],c2[5]+1) or c1[5] in range(c2[4],c2[5]+1)) def split(c1,c2): x1,x2,y1,y2,z1,z2 = c1 lx,hx,ly,hy,lz,hz = c2 xos = max(lx,x1) xoe = min(hx,x2) yos = max(ly,y1) yoe = min(hy,y2) zos = max(lz,z1) zoe = min(hz,z2) v = 0 for x in [(lx,xos-1),(xos,xoe),(xoe+1,hx)]: for y in [(ly,yos-1),(yos,yoe),(yoe+1,hy)]: for z in [(lz,zos-1),(zos,zoe),(zoe+1,hz)]: v += volume((*x,*y,*z)) if volume((*x,*y,*z)) > 0 and (x,y,z) != ((xos,xoe),(yos,yoe),(zos,zoe)): yield (*x,*y,*z) def init(steps): cubes = {} for m,x1,x2,y1,y2,z1,z2 in steps: if not (-50 <= x1 <= 50 and -50 <= x2 <= 50): continue for x in range(x1,x2+1): if not (-50 <= y1 <= 50 and -50 <= y2 <= 50): continue for y in range(y1,y2+1): if not (-50 <= z1 <= 50 and -50 <= z2 <= 50): continue for z in range(z1,z2+1): cubes[(x,y,z)] = m return cubes def reboot(steps): cubes = {} for c1 in steps: m,c1 = c1[0],c1[1:] atm = [k for k in cubes.keys()] for c2 in atm: om = cubes[c2] if intersect(c1,c2) or intersect(c2,c1): for c in split(c1,c2): if not (intersect(c,c1) or intersect(c1,c)): cubes[c] = om cubes.pop(c2) cubes[c1] = m return cubes if __name__ == '__main__': nums = map(lambda x: (x[0],int(x[1]),int(x[2]),int(x[3]),int(x[4]),int(x[5]),int(x[6])),[parse(l).groups() for l in open(sys.argv[1])]) nums = [n for n in nums] # challenge 1 cubes1 = init(nums) c = Counter([v for k,v in cubes1.items() if -50 <= k[0] <= 50 and -50 <= k[1] <= 50 and -50 <= k[2] <= 50]) res1 = str(c.most_common(2)) print("challenge 1:" + "\n" + res1 + "\n") # challenge 2 cubes2 = reboot(nums) res2 = str(count_cubes(cubes2)) print("challenge 2:" + "\n" + res2 + "\n")