d12p1
This commit is contained in:
78
day12/d12p1.swift
Normal file
78
day12/d12p1.swift
Normal file
@@ -0,0 +1,78 @@
|
||||
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)
|
Reference in New Issue
Block a user