From e5a9d98609e168bf06d2752fe440af409cfe454f Mon Sep 17 00:00:00 2001 From: Jeremy Kaplan Date: Wed, 22 Dec 2021 19:50:28 -0800 Subject: [PATCH] 2021 Day 22 Part 2 --- 2021/day22/main.go | 148 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/2021/day22/main.go b/2021/day22/main.go index bf60801..7987ff3 100644 --- a/2021/day22/main.go +++ b/2021/day22/main.go @@ -10,6 +10,7 @@ func main() { lines := aoc.Input().ReadLines("day22.txt") steps := parseInput(lines) fmt.Println(part1(steps)) + fmt.Println(part2(steps)) } func parseInput(lines []string) (steps []Step) { @@ -25,6 +26,10 @@ func part1(steps []Step) int { return r.CountOn() } +func part2(steps []Step) int { + return reboot(steps) +} + type Step struct { op string x1, x2 int @@ -80,3 +85,146 @@ func (r Reactor) CountOn() (count int) { } 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 +}