|
|
|
@ -1,5 +1,4 @@ |
|
|
|
|
import re |
|
|
|
|
from functools import reduce |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def readInstructions(fileName): |
|
|
|
@ -8,54 +7,33 @@ def readInstructions(fileName): |
|
|
|
|
lines = file.read().splitlines() |
|
|
|
|
for line in lines: |
|
|
|
|
result = re.search(r"x=(.+)\.\.(.+),y=(.+)\.\.(.+),z=(.+)\.\.(.+)", line).groups() |
|
|
|
|
isOn = line.startswith("on") |
|
|
|
|
instructions.append((isOn, tuple(int(r) for r in result))) |
|
|
|
|
sign = 1 if line.startswith("on") else -1 |
|
|
|
|
result = tuple((sign,)) + tuple(result) |
|
|
|
|
instructions.append(tuple(int(r) for r in result)) |
|
|
|
|
return instructions |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def contains(a, b): |
|
|
|
|
ax1, ax2, ay1, ay2, az1, az2 = a |
|
|
|
|
bx1, bx2, by1, by2, bz1, bz2 = b |
|
|
|
|
return ax1 <= bx1 and ax2 >= bx2 and ay1 <= by1 and ay2 >= by2 and az1 <= bz1 and az2 >= bz2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def volume(cube): |
|
|
|
|
x1, x2, y1, y2, z1, z2 = cube |
|
|
|
|
return abs(x2 - x1) * abs(y2 - y1) * abs(z2 - z1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def sub(a, b): |
|
|
|
|
ax1, ax2, ay1, ay2, az1, az2 = a |
|
|
|
|
bx1, bx2, by1, by2, bz1, bz2 = b |
|
|
|
|
sign, x1, x2, y1, y2, z1, z2 = cube |
|
|
|
|
return (x2 - x1 + 1) * (y2 - y1 + 1) * (z2 - z1 + 1) * sign |
|
|
|
|
|
|
|
|
|
# if currentCube contains knownCube, remove knownCube |
|
|
|
|
if contains(b, a): |
|
|
|
|
return [] |
|
|
|
|
|
|
|
|
|
# if there are no intersections, do nothing |
|
|
|
|
def intersect(a, b): |
|
|
|
|
_, ax1, ax2, ay1, ay2, az1, az2 = a |
|
|
|
|
bSign, bx1, bx2, by1, by2, bz1, bz2 = b |
|
|
|
|
if ax1 > bx2 or ax2 < bx1 or ay1 > by2 or ay2 < by1 or az1 > bz2 or az2 < bz1: |
|
|
|
|
return [a] |
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
xSplits = filter(lambda x: ax1 < x < ax2, [bx1, bx2]) |
|
|
|
|
ySplits = filter(lambda y: ay1 < y < ay2, [by1, by2]) |
|
|
|
|
zSplits = filter(lambda z: az1 < z < az2, [bz1, bz2]) |
|
|
|
|
x1 = max(ax1, bx1) |
|
|
|
|
x2 = min(ax2, bx2) |
|
|
|
|
y1 = max(ay1, by1) |
|
|
|
|
y2 = min(ay2, by2) |
|
|
|
|
z1 = max(az1, bz1) |
|
|
|
|
z2 = min(az2, bz2) |
|
|
|
|
|
|
|
|
|
xValues = [ax1, *xSplits, ax2] |
|
|
|
|
yValues = [ay1, *ySplits, ay2] |
|
|
|
|
zValues = [az1, *zSplits, az2] |
|
|
|
|
sign = -bSign |
|
|
|
|
|
|
|
|
|
results = [] |
|
|
|
|
for i in range(len(xValues) - 1): |
|
|
|
|
for j in range(len(yValues) - 1): |
|
|
|
|
for k in range(len(zValues) - 1): |
|
|
|
|
newC = xValues[i], yValues[j], zValues[k], xValues[i + 1], yValues[j + 1], zValues[k + 1] |
|
|
|
|
if not contains(b, newC): |
|
|
|
|
results.append(newC) |
|
|
|
|
return results |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def flatMap(func, elements): |
|
|
|
|
return [j for i in elements for j in func(i)] |
|
|
|
|
return sign, x1, x2, y1, y2, z1, z2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def reboot(): |
|
|
|
@ -63,21 +41,18 @@ def reboot(): |
|
|
|
|
|
|
|
|
|
cubes = [] |
|
|
|
|
|
|
|
|
|
for turnOn, coords in instructions: |
|
|
|
|
x1, x2, y1, y2, z1, z2 = coords |
|
|
|
|
currentCube = x1, x2 + 1, y1, y2 + 1, z1, z2 + 1 |
|
|
|
|
for currentCube in instructions: |
|
|
|
|
|
|
|
|
|
cubes = flatMap(lambda c: sub(c, currentCube), cubes) |
|
|
|
|
for cube in cubes.copy(): |
|
|
|
|
if intersection := intersect(currentCube, cube): |
|
|
|
|
cubes.append(intersection) |
|
|
|
|
|
|
|
|
|
# add to set if 'on' |
|
|
|
|
if turnOn: |
|
|
|
|
if currentCube[0] == 1: |
|
|
|
|
cubes.append(currentCube) |
|
|
|
|
|
|
|
|
|
onCount = sum(map(volume, cubes)) |
|
|
|
|
print(onCount) |
|
|
|
|
filteredCubes = filter(lambda c: -50 <= c[1] <= 50, cubes) |
|
|
|
|
print(sum(map(lambda c: volume(c), filteredCubes))) |
|
|
|
|
print(sum(map(lambda c: volume(c), cubes))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reboot() |
|
|
|
|
|
|
|
|
|
# on x=-54112..-39298,y=-85059..-49293,z=-27449..7877 |
|
|
|
|
# on x=967..23432,y=45373..81175,z=27513..53682 |