Day 22 part 2
This commit is contained in:
parent
1923e8ec0b
commit
6427bb0aac
1 changed files with 67 additions and 31 deletions
98
day22.swift
98
day22.swift
|
@ -3,44 +3,57 @@ import Foundation
|
|||
@main
|
||||
struct Day22: Puzzle {
|
||||
func run() {
|
||||
var cube: [Point: Bool] = [:]
|
||||
let activeRange = -50...50
|
||||
|
||||
let scanner = Scanner(string: input)
|
||||
var cubes: [Cube] = []
|
||||
|
||||
while !scanner.isAtEnd {
|
||||
let (command, xrange, yrange, zrange) = scanner.line()
|
||||
if let xrange = xrange.intersection(with: activeRange) {
|
||||
for x in xrange.clamped(to: activeRange) {
|
||||
if let yrange = yrange.intersection(with: activeRange) {
|
||||
for y in yrange.clamped(to: activeRange) {
|
||||
if let zrange = zrange.intersection(with: activeRange) {
|
||||
for z in zrange.clamped(to: activeRange) {
|
||||
cube[Point(x: x, y: y, z: z)] = command
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cubes.append(scanner.cube())
|
||||
}
|
||||
|
||||
var xStepsSet: Set<Int> = []
|
||||
var yStepsSet: Set<Int> = []
|
||||
var zStepsSet: Set<Int> = []
|
||||
|
||||
var sum = 0
|
||||
for x in activeRange {
|
||||
for y in activeRange {
|
||||
for z in activeRange {
|
||||
sum += cube[Point(x: x, y: y, z: z), default: false] ? 1 : 0
|
||||
for cube in cubes {
|
||||
xStepsSet.insert(cube.start.x)
|
||||
xStepsSet.insert(cube.end.x + 1)
|
||||
yStepsSet.insert(cube.start.y)
|
||||
yStepsSet.insert(cube.end.y + 1)
|
||||
zStepsSet.insert(cube.start.z)
|
||||
zStepsSet.insert(cube.end.z + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
print("Part 1:", sum)
|
||||
}
|
||||
}
|
||||
|
||||
extension ClosedRange {
|
||||
func intersection(with other: Self) -> Self? {
|
||||
guard upperBound >= other.lowerBound && lowerBound <= other.upperBound else { return nil }
|
||||
return clamped(to: other)
|
||||
var xSteps = xStepsSet.sorted()
|
||||
var ySteps = yStepsSet.sorted()
|
||||
var zSteps = zStepsSet.sorted()
|
||||
|
||||
let firstX = xSteps.removeFirst()
|
||||
let firstY = ySteps.removeFirst()
|
||||
let firstZ = zSteps.removeFirst()
|
||||
|
||||
var part2 = 0
|
||||
|
||||
var x0 = firstX
|
||||
for x in xSteps {
|
||||
let possibleX = cubes.filter { $0.xRange.overlaps(x0..<x) }
|
||||
var y0 = firstY
|
||||
for y in ySteps {
|
||||
let possibleY = possibleX.filter { $0.yRange.overlaps(y0..<y) }
|
||||
var z0 = firstZ
|
||||
for z in zSteps {
|
||||
let state = possibleY.lazy.reversed().first { $0.zRange.overlaps(z0..<z) }?.state ?? false
|
||||
|
||||
if state {
|
||||
part2 += (x - x0) * (y - y0) * (z - z0)
|
||||
}
|
||||
z0 = z
|
||||
}
|
||||
y0 = y
|
||||
}
|
||||
x0 = x
|
||||
}
|
||||
|
||||
print("Part 2:", part2)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +63,20 @@ struct Point: Hashable {
|
|||
var z: Int
|
||||
}
|
||||
|
||||
struct Cube {
|
||||
var start: Point
|
||||
var end: Point
|
||||
var state: Bool
|
||||
|
||||
var xRange: ClosedRange<Int> { start.x...end.x }
|
||||
var yRange: ClosedRange<Int> { start.y...end.y }
|
||||
var zRange: ClosedRange<Int> { start.z...end.z }
|
||||
|
||||
func contains(_ point: Point) -> Bool {
|
||||
xRange.contains(point.x) && yRange.contains(point.y) && zRange.contains(point.z)
|
||||
}
|
||||
}
|
||||
|
||||
extension Scanner {
|
||||
func onOff() -> Bool {
|
||||
if scanString("on") != nil {
|
||||
|
@ -84,6 +111,15 @@ extension Scanner {
|
|||
let zRange = range()
|
||||
return (command, xRange, yRange, zRange)
|
||||
}
|
||||
|
||||
func cube() -> Cube {
|
||||
let (state, xrange, yrange, zrange) = line()
|
||||
return Cube(
|
||||
start: Point(x: xrange.lowerBound, y: yrange.lowerBound, z: zrange.lowerBound),
|
||||
end: Point(x: xrange.upperBound, y: yrange.upperBound, z: zrange.upperBound),
|
||||
state: state
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let input = """
|
||||
|
|
Loading…
Add table
Reference in a new issue