79 lines
2.2 KiB
Swift
79 lines
2.2 KiB
Swift
import Foundation
|
|
|
|
struct Plot : Hashable, CustomStringConvertible {
|
|
let x: Int
|
|
let y: Int
|
|
var description: String { return "Plot(\(x), \(y))" }
|
|
}
|
|
|
|
struct Map : CustomStringConvertible {
|
|
let map: [[Character]]
|
|
let (w, h): (Int, Int)
|
|
var visited: [[Bool]]
|
|
|
|
var description: String {
|
|
var ret: String = "\(w)x\(h):\n"
|
|
for i in 0..<map.count {
|
|
for j in 0..<map[i].count {
|
|
ret.append(map[i][j])
|
|
ret.append(visited[i][j] ? "." : " ")
|
|
}
|
|
ret.append("\n")
|
|
}
|
|
return ret
|
|
}
|
|
init(_ map: [[Character]]) {
|
|
self.map = map
|
|
self.visited = map.map { $0.map { _ in false } }
|
|
self.h = map.count
|
|
self.w = map[0].count
|
|
}
|
|
|
|
// visits a plot; returns its perimeter contribution & unvisited neighbors
|
|
mutating func visit(_ plot: Plot) -> (Int, [Plot]) {
|
|
let (x, y) = (plot.x, plot.y)
|
|
visited[x][y] = true
|
|
let all_nbs = [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]
|
|
let peri = all_nbs.filter { i, j in
|
|
i < 0 || j < 0 || i >= h || j >= w || map[i][j] != map[x][y]
|
|
}.count
|
|
let nbs = all_nbs.filter { i, j in
|
|
i >= 0 && j >= 0 && i < h && j < w &&
|
|
map[i][j] == map[x][y] &&
|
|
!visited[i][j]
|
|
}.map { i, j in Plot(x: i, y: j) }
|
|
return (peri, nbs)
|
|
}
|
|
|
|
mutating func visitAll(from plot: Plot) -> Int {
|
|
var q: Set<Plot> = [plot]
|
|
var peri = 0
|
|
var area = 0
|
|
while !q.isEmpty {
|
|
let currentPlot = q.removeFirst()
|
|
let (newPeri, newNBs) = visit(currentPlot)
|
|
peri += newPeri
|
|
area += 1
|
|
q.formUnion(newNBs)
|
|
}
|
|
return peri * area
|
|
}
|
|
}
|
|
|
|
func readInput(_ filePath: String) throws -> Map {
|
|
let content = try String(contentsOfFile: filePath, encoding: .ascii)
|
|
return Map(content.split(separator: "\n").map(Array.init))
|
|
}
|
|
|
|
var map = try readInput(CommandLine.arguments[1])
|
|
print(map)
|
|
var answer = 0
|
|
for i in 0..<map.h {
|
|
for j in 0..<map.w {
|
|
if !map.visited[i][j] {
|
|
answer += map.visitAll(from: Plot(x: i, y: j))
|
|
}
|
|
}
|
|
}
|
|
print(answer)
|