56 lines
1.8 KiB
Swift
56 lines
1.8 KiB
Swift
import Foundation
|
|
|
|
struct Point : Hashable {
|
|
let x: Int
|
|
let y: Int
|
|
}
|
|
|
|
func readInput(_ filePath: String) throws -> (Int, Int, [Character: [Point]]) {
|
|
let content = try String(contentsOfFile: filePath, encoding: .ascii)
|
|
let lines = content.split(separator: "\n").map(Array.init)
|
|
let antennas = lines.enumerated().flatMap { i, line in
|
|
line.enumerated().compactMap { j, cell in
|
|
cell == "." ? nil : (cell, i, j)
|
|
}
|
|
}
|
|
var map: [Character: [Point]] = [:]
|
|
for (type, i, j) in antennas {
|
|
let current = map[type, default: []]
|
|
map[type] = current + [Point(x: i, y: j)]
|
|
}
|
|
return (lines.count, lines[0].count, map)
|
|
}
|
|
|
|
func nodes(_ antennas: [Point], h: Int, w: Int) -> Set<Point> {
|
|
var nodes: Set<Point> = []
|
|
for i in 0..<antennas.count {
|
|
for j in i+1..<antennas.count {
|
|
let (a, b) = (antennas[i], antennas[j])
|
|
// (k+1)a - kb going one way
|
|
var k = 0
|
|
var next = Point(x: (k+1)*a.x - k*b.x, y: (k+1)*a.y - k*b.y)
|
|
while next.x >= 0 && next.x < h && next.y >= 0 && next.y < w {
|
|
nodes.insert(next)
|
|
k += 1
|
|
next = Point(x: (k+1)*a.x - k*b.x, y: (k+1)*a.y - k*b.y)
|
|
}
|
|
// going the other way
|
|
k = -1
|
|
next = Point(x: (k+1)*a.x - k*b.x, y: (k+1)*a.y - k*b.y)
|
|
while next.x >= 0 && next.x < h && next.y >= 0 && next.y < w {
|
|
nodes.insert(next)
|
|
k -= 1
|
|
next = Point(x: (k+1)*a.x - k*b.x, y: (k+1)*a.y - k*b.y)
|
|
}
|
|
}
|
|
}
|
|
return nodes
|
|
}
|
|
|
|
let (height, width, antennas) = try readInput(CommandLine.arguments[1])
|
|
let answer = antennas
|
|
.map { c, points in nodes(points, h: height, w: width) }
|
|
.reduce(Set([]), { acc, x in acc.union(x) })
|
|
.count
|
|
print(answer)
|