type subcubes map[cuboid]int
func solveSecond(cbs []cuboid) int {
m := subcubes{}
for _, cube := range cbs {
subMap := subcubes{}
for orig := range m {
ovrlp := overlap(cube, orig)
if ovrlp.state == "noop" {
continue
}
// do not count repeatedly the overlapping part
// m[orig] can be 0, -1 and 1.
// 0 means it was an "off" state
// if it was 1, now we change it to -1, so adding a new cube with
// state = "on" will change it to 0.
subMap[ovrlp] -= m[orig]
}
if cube.state == "on" {
subMap[cube] += 1
}
for c := range subMap {
m[c] += subMap[c]
}
}
var sum int
for cube, v := range m {
sum += cube.size() * v
}
return sum
}
func (c cuboid) size() int {
return (c.xmax - c.xmin + 1) * (c.ymax - c.ymin + 1) * (c.zmax - c.zmin + 1)
}
func overlap(first, second cuboid) cuboid {
// return none, if there is no overlap in one of the dimensions
if first.xmax < second.xmin || second.xmax < first.xmin ||
first.ymax < second.ymin || second.ymax < first.ymin ||
first.zmax < second.zmin || second.zmax < first.zmin {
return cuboid{state: "noop"}
}
return cuboid{"",
max(first.xmin, second.xmin), min(first.xmax, second.xmax),
max(first.ymin, second.ymin), min(first.ymax, second.ymax),
max(first.zmin, second.zmin), min(first.zmax, second.zmax),
}
}