// // File.swift // // // Created by Max Nuding on 05.12.21. // import Foundation import Runner struct Line: CustomStringConvertible { let from: Point let to: Point var description: String { "\(from.x),\(from.y) -> \(to.x),\(to.y)" } var isStraight: Bool { from.x == to.x || from.y == to.y } init(inputLine: String) { let points = inputLine.components(separatedBy: " -> ") let res = points.map { point in point.split(separator: ",").map { Int($0)! } } from = Point(x: res[0][0], y: res[0][1]) to = Point(x: res[1][0], y: res[1][1]) } func getCoveredPoints() -> [Point] { var points = [Point]() let startX = min(from.x, to.x) let endX = max(from.x, to.x) let startY = min(from.y, to.y) let endY = max(from.y, to.y) if isStraight { for x in startX...endX { for y in startY...endY { points.append(Point(x: x, y: y)) } } } else { var x = from.x var y = from.y let dirX = from.x > to.x ? -1 : 1 let dirY = from.y > to.y ? -1 : 1 while x != to.x { points.append(Point(x: x, y: y)) x += dirX y += dirY } points.append(to) } return points } } struct Point: Hashable { let x: Int let y: Int } struct Field: CustomStringConvertible { var coveredPoints = [Point: Int]() var description: String { let minX = 0 let minY = 0 let maxX = coveredPoints.max(by: {$0.key.x < $1.key.x})?.key.x ?? 0 let maxY = coveredPoints.max(by: {$0.key.y < $1.key.y})?.key.y ?? 0 var desc = "Field from \(minX), \(minY) to \(maxX), \(maxY))\n" for y in minY...maxY { for x in minX...maxX { let val = coveredPoints[Point(x: x, y: y)] ?? 0 desc += val == 0 ? "." : "\(val)" } desc += "\n" } return desc } mutating func cover(point: Point) { coveredPoints[point] = (coveredPoints[point] ?? 0) + 1 } } struct Day05: Runnable { let inputPath: String func run() { let input = try! String(contentsOfFile: inputPath) let lines = input .components(separatedBy: .newlines) .filter { !$0.isEmpty } .compactMap { Line(inputLine: $0) } run(lines: lines.filter { $0.isStraight }) run(lines: lines) } func run(lines: [Line]) { var field = Field() //let straightLines = lines.filter { $0.isStraight } for line in lines { for point in line.getCoveredPoints() { field.cover(point: point) } } //print(field) print(field.coveredPoints.filter { $0.value > 1 }.count) } }