// // File.swift // // // Created by Max Nuding on 17.12.21. // import Foundation import Runner import Collections struct Point:Hashable { var x: Int var y: Int } struct Area { let topLeft: Point let botRight: Point init(x: String, y: String) { let xVals = x[x.index(x.startIndex, offsetBy: 2)...].components(separatedBy: "..").map { Int($0)! } let yVals = y[y.index(y.startIndex, offsetBy: 2)...].components(separatedBy: "..").map { Int($0)! } topLeft = Point(x: xVals.first!, y: yVals.last!) botRight = Point(x: xVals.last!, y: yVals.first!) } func contains(point: Point) -> Bool { point.x >= topLeft.x && point.x <= botRight.x && point.y <= topLeft.y && point.y >= botRight.y } func overshot(point: Point) -> Bool { point.y < botRight.y || point.x > botRight.x } } struct Probe { var position = Point(x: 0, y: 0) var velocity: Point mutating func move() { position.x += velocity.x position.y += velocity.y if velocity.x < 0 { velocity.x += 1 } else if velocity.x > 0 { velocity.x -= 1 } velocity.y -= 1 } } class Day17: Runnable { let inputPath: String required init(inputPath: String) { self.inputPath = inputPath } public func run() { let input = try! String(contentsOfFile: inputPath) let parts = input .trimmingCharacters(in: .newlines) .components(separatedBy: ": ") .last! .components(separatedBy: ", ") let area = Area(x: parts.first!, y: parts.last!) var maxY = Int.min var found = [Point]() found.reserveCapacity(3000) for x in 0...500 { for y in -500...500 { let velocity = Point(x: x, y: y) var probe = Probe(velocity: velocity) var maxYCurrent = Int.min repeat { probe.move() if probe.position.y > maxYCurrent { maxYCurrent = probe.position.y } if area.contains(point: probe.position) { if maxYCurrent > maxY { maxY = maxYCurrent } found.append(velocity) break } } while !area.overshot(point: probe.position) } } print(maxY) print(Set(found).count) } }