Something went wrong. Try again.
Code for the Advent of Code event
aoc advent-of-code
Something went wrong. Try again.
2.2 kB · 84 lines
Ruby
at rust
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485#!/usr/bin/env ruby# frozen_string_literal: true
class Cuboid attr_reader :left, :right, :bottom, :top, :front, :back
def initialize(left, right, bottom, top, front, back) @left = left @right = right @bottom = bottom @top = top @front = front @back = back @removed = [] end
def width = (right - left + 1).abs def height = (top - bottom + 1).abs def depth = (back - front + 1).abs
def volume (width * depth * height) - @removed.sum(&:volume) end
def clamp(range) Cuboid.new left.clamp(range), right.clamp(range), bottom.clamp(range), top.clamp(range), front.clamp(range), back.clamp(range) end
def clamp!(range) @left = left.clamp range @right = right.clamp range @bottom = bottom.clamp range @top = top.clamp range @front = front.clamp range @back = back.clamp range self end
def intersects?(other) top >= other.bottom && bottom <= other.top && right >= other.left && left <= other.right && back >= other.front && front <= other.back end
def intersection(other) return nil unless intersects? other bottom = [@bottom, other.bottom].max top = [@top, other.top].min left = [@left, other.left].max right = [@right, other.right].min front = [@front, other.front].max back = [@back, other.back].min Cuboid.new(left, right, bottom, top, front, back) end
def remove!(cuboid) @removed.each { |r| r.remove!(cuboid.intersection(r)) if r.intersects? cuboid } @removed << cuboid end
def to_s "(X=#{left}..#{right},Y=#{bottom}..#{top},Z=#{front}..#{back})" endend
def format_number(n) n.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1 ').reverseend
reactor = []
ARGF.each_line do |line| op, ranges = line.split.then { [_1.to_sym, _2] } left, right, bottom, top, front, back = ranges.scan(/-?\d+/).map(&:to_i) cuboid = Cuboid.new(left, right, bottom, top, front, back) intersecting = reactor.select { |c| cuboid.intersects? c } intersecting.each do |c| intersection = c.intersection cuboid c.remove! intersection end reactor << cuboid if op == :onend
puts reactor.sum(&:volume)