Compare commits
No commits in common. "93f1c73fbf56dd670c4693c60ebe6a61ddeda858" and "1ff50f072e98263f9bb489ef98a59f7052ca6e2d" have entirely different histories.
93f1c73fbf
...
1ff50f072e
@ -9,7 +9,7 @@ import Foundation
|
|||||||
import Runner
|
import Runner
|
||||||
import Collections
|
import Collections
|
||||||
|
|
||||||
struct Coord: Hashable {
|
struct Coord {
|
||||||
let row: Int
|
let row: Int
|
||||||
let col: Int
|
let col: Int
|
||||||
|
|
||||||
@ -33,34 +33,31 @@ struct Coord: Hashable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Field:Sequence, IteratorProtocol {
|
struct Field:Sequence, IteratorProtocol {
|
||||||
typealias Element = Coord
|
|
||||||
let numbers: [[Int]]
|
let numbers: [[Int]]
|
||||||
let numCols: Int
|
let numCols: Int
|
||||||
let numRows: Int
|
let numRows: Int
|
||||||
|
|
||||||
var neighbors = [Coord:[Coord]]()
|
|
||||||
|
|
||||||
var current: Coord? = Coord(row: 0, col: 0)
|
var current: Coord? = Coord(row: 0, col: 0)
|
||||||
|
|
||||||
init(numbers: [[Int]]) {
|
init(numbers: [[Int]]) {
|
||||||
self.numbers = numbers
|
self.numbers = numbers
|
||||||
numCols = numbers.first?.count ?? 0
|
numCols = numbers.first!.count
|
||||||
numRows = numbers.count
|
numRows = numbers.count
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func getNeighborsCoordsFor(coord: Coord) -> [Coord] {
|
func getNeighborsCoordsFor(coord: Coord) -> [Coord] {
|
||||||
let n = neighbors[coord] ?? [coord.getAbove(), coord.getRight(), coord.getBelow(), coord.getLeft()]
|
return [coord.getAbove(), coord.getRight(), coord.getBelow(), coord.getLeft()]
|
||||||
.compactMap { $0 }
|
.compactMap { $0 }
|
||||||
.filter { $0.row < numRows && $0.col < numCols }
|
.filter { $0.row < numRows && $0.col < numCols }
|
||||||
neighbors[coord] = n
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func isLowPointAt(coord: Coord) -> Bool {
|
func lowPointValueAt(coord: Coord) -> Int? {
|
||||||
let value = self[coord]
|
let value = numbers[coord.row][coord.col]
|
||||||
return getNeighborsCoordsFor(coord: coord)
|
return getNeighborsCoordsFor(coord: coord)
|
||||||
.map { numbers[$0.row][$0.col] }
|
.map { numbers[$0.row][$0.col] }
|
||||||
.allSatisfy { $0 > value }
|
.allSatisfy { $0 > value }
|
||||||
|
? value
|
||||||
|
: nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getNextCoord() -> Coord? {
|
private func getNextCoord() -> Coord? {
|
||||||
@ -82,59 +79,19 @@ struct Field:Sequence, IteratorProtocol {
|
|||||||
}
|
}
|
||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
|
|
||||||
subscript(index: Coord) -> Int {
|
|
||||||
get {
|
|
||||||
numbers[index.row][index.col]
|
|
||||||
}/*
|
|
||||||
set(newValue) {
|
|
||||||
// Perform a suitable setting action here.
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Day09: Runnable {
|
struct Day09: Runnable {
|
||||||
let inputPath: String
|
let inputPath: String
|
||||||
var lowestNeighbors = [Coord: Coord]()
|
|
||||||
var lowPoints = Set<Coord>()
|
|
||||||
var field = Field(numbers: [[Int]]())
|
|
||||||
|
|
||||||
required init(inputPath: String) {
|
func run() {
|
||||||
self.inputPath = inputPath
|
|
||||||
}
|
|
||||||
|
|
||||||
public func run() {
|
|
||||||
let input = try! String(contentsOfFile: inputPath)
|
let input = try! String(contentsOfFile: inputPath)
|
||||||
let entries = input
|
let entries = input
|
||||||
.trimmingCharacters(in: .newlines)
|
.trimmingCharacters(in: .newlines)
|
||||||
.components(separatedBy: .newlines)
|
.components(separatedBy: .newlines)
|
||||||
.map { line in line.map { $0.wholeNumberValue! } }
|
.map { line in line.map { $0.wholeNumberValue! } }
|
||||||
field = Field(numbers: entries)
|
let field = Field(numbers: entries)
|
||||||
lowPoints = Set(field.filter { field.isLowPointAt(coord: $0) })
|
let sum = field.compactMap { field.lowPointValueAt(coord: $0) }.reduce(0, { $0 + $1 + 1 })
|
||||||
|
|
||||||
//Part 1
|
|
||||||
let sum = lowPoints.map { field[$0] }.reduce(0, +) + lowPoints.count
|
|
||||||
print(sum)
|
print(sum)
|
||||||
|
|
||||||
// Part 2:
|
|
||||||
var basinSize = [Coord: Int]()
|
|
||||||
for coord in field {
|
|
||||||
guard field[coord] != 9 else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let bl = basinLocation(for: coord)
|
|
||||||
basinSize[bl, default: 0] += 1
|
|
||||||
}
|
|
||||||
let result = basinSize.values.sorted(by: >)[0..<3].reduce(1, *)
|
|
||||||
print(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func basinLocation(for coord: Coord) -> Coord {
|
|
||||||
guard !lowPoints.contains(coord) else {
|
|
||||||
return coord
|
|
||||||
}
|
|
||||||
let closestNeighbor = lowestNeighbors[coord] ?? field.getNeighborsCoordsFor(coord: coord).min(by: { field[$0] < field[$1] })!
|
|
||||||
lowestNeighbors[coord] = closestNeighbor
|
|
||||||
return basinLocation(for: closestNeighbor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Runner
|
import Runner
|
||||||
|
|
||||||
//Runner(target: Day09.self, day: "09", isTest: true).run()
|
Runner(target: Day09.self, day: "09", isTest: true).run()
|
||||||
Runner(target: Day09.self, day: "09", isTest: false).run()
|
//Runner(target: Day09.self, day: "09", isTest: false).run()
|
||||||
|
Loading…
Reference in New Issue
Block a user