aoc2021/Sources/05/05.swift
2021-12-05 11:43:49 +01:00

108 lines
2.9 KiB
Swift

//
// 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)
}
}