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.
91 lines
2.9 KiB
91 lines
2.9 KiB
#!/usr/bin/env python3
|
|
|
|
import sys,re
|
|
from collections import Counter
|
|
|
|
def parse(l):
|
|
return re.compile(r"(?P<mode>\w+) x=(?P<x1>-?\d+)..(?P<x2>-?\d+),y=(?P<y1>-?\d+)..(?P<y2>-?\d+),z=(?P<z1>-?\d+)..(?P<z2>-?\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")
|
|
|
|
|