Watch
1
0
Fork
You've already forked advent-of-code
0

2021 Day 22 Part 2

This commit is contained in:
Jeremy Kaplan 2021-12-22 19:50:28 -08:00
commit e5a9d98609

View file

@ -10,6 +10,7 @@ func main() {
lines := aoc.Input().ReadLines("day22.txt") lines := aoc.Input().ReadLines("day22.txt")
steps := parseInput(lines) steps := parseInput(lines)
fmt.Println(part1(steps)) fmt.Println(part1(steps))
fmt.Println(part2(steps))
} }
func parseInput(lines []string) (steps []Step) { func parseInput(lines []string) (steps []Step) {
@ -25,6 +26,10 @@ func part1(steps []Step) int {
return r.CountOn() return r.CountOn()
} }
func part2(steps []Step) int {
return reboot(steps)
}
type Step struct { type Step struct {
op string op string
x1, x2 int x1, x2 int
@ -80,3 +85,146 @@ func (r Reactor) CountOn() (count int) {
} }
return return
} }
func reboot(steps []Step) int {
var cells []Cuboid
for _, s := range steps {
c := Cuboid{
x: Interval{s.x1, s.x2},
y: Interval{s.y1, s.y2},
z: Interval{s.z1, s.z2},
}
cells = cut(cells, c)
if s.op == "on" {
cells = append(cells, c)
}
}
return countOn(cells)
}
func countOn(cells []Cuboid) (count int) {
for _, cell := range cells {
count += cell.Size()
}
return
}
func cut(cells []Cuboid, cutter Cuboid) (stillOn []Cuboid) {
for _, cell := range cells {
ix := cell.Intersect(cutter)
if ix.Empty() {
stillOn = append(stillOn, cell)
continue
}
mm := cell.Minus(*ix)
stillOn = append(stillOn, mm...)
}
return
}
type Cuboid struct {
x, y, z Interval
}
func (c Cuboid) String() string {
return fmt.Sprintf("x: %s, y: %s, z: %s", c.x, c.y, c.z)
}
func (c *Cuboid) Empty() bool {
return c == nil || c.x.Empty() || c.y.Empty() || c.z.Empty()
}
func (c Cuboid) Size() int {
return c.x.Size() * c.y.Size() * c.z.Size()
}
func (c Cuboid) Intersect(d Cuboid) (intersection *Cuboid) {
ix := c.x.Intersect(d.x)
if ix.Empty() {
return nil
}
iy := c.y.Intersect(d.y)
if iy.Empty() {
return nil
}
iz := c.z.Intersect(d.z)
if iz.Empty() {
return nil
}
return &Cuboid{ix, iy, iz}
}
func (c Cuboid) Minus(d Cuboid) []Cuboid {
x0, x1, x2 := c.x.Split(d.x)
y0, y1, y2 := c.y.Split(d.y)
z0, z1, z2 := c.z.Split(d.z)
return nonEmpty([]Cuboid{
{x0, y0, z0},
{x0, y0, z1},
{x0, y0, z2},
{x0, y1, z0},
{x0, y1, z1},
{x0, y1, z2},
{x0, y2, z0},
{x0, y2, z1},
{x0, y2, z2},
{x1, y0, z0},
{x1, y0, z1},
{x1, y0, z2},
{x1, y1, z0},
{x1, y1, z2},
{x1, y2, z0},
{x1, y2, z1},
{x1, y2, z2},
// {x1, y1, z1}, // Don't include the intersection block
{x2, y0, z0},
{x2, y0, z1},
{x2, y0, z2},
{x2, y1, z0},
{x2, y1, z1},
{x2, y1, z2},
{x2, y2, z0},
{x2, y2, z1},
{x2, y2, z2},
})
}
func nonEmpty(cs []Cuboid) (nonEmpty []Cuboid) {
for _, c := range cs {
if !c.Empty() {
nonEmpty = append(nonEmpty, c)
}
}
return
}
type Interval [2]int
func (i Interval) String() string {
return fmt.Sprintf("[%d, %d]", i[0], i[1])
}
func (i Interval) Empty() bool {
return i.Size() <= 0
}
func (i Interval) Size() int {
return i[1] - i[0] + 1
}
func (i Interval) Intersect(j Interval) Interval {
return Interval{
max(i[0], j[0]),
min(i[1], j[1]),
}
}
func (i Interval) Split(j Interval) (prefix, inside, suffix Interval) {
prefix = Interval{i[0], j[0] - 1}
inside = Interval{j[0], j[1]}
suffix = Interval{j[1] + 1, i[1]}
return
}