both parts

This commit is contained in:
Max Nuding 2021-12-15 14:32:20 +01:00
parent 2239760ce2
commit c7e8bf103e
Signed by: phlaym
GPG Key ID: A06651BAB6777237

View File

@ -38,22 +38,11 @@ class Day15: Runnable {
self.inputPath = inputPath self.inputPath = inputPath
} }
public func run() { private func expandMap() {
let input = try! String(contentsOfFile: inputPath)
parts = input
.trimmingCharacters(in: .newlines)
.components(separatedBy: .newlines)
.map { Array($0) }
.map { ar in ar.map {c in ThreatLevel(c.description)!} }
lastRow = parts.count - 1
lastCol = (parts.first?.count ?? 0) - 1
var tmpParts = parts var tmpParts = parts
for (rowNum, row) in tmpParts.enumerated() { for (rowNum, row) in tmpParts.enumerated() {
let newRow = [Int](0...4).flatMap { cr in let newRow = [Int](0...4).flatMap { cr in
row row.map { rv in cr + rv }.map { $0 > 9 ? $0 - 9 : $0 }
.map { rv in cr + rv }
.map { $0 > 9 ? $0 - 9 : $0 }
} }
parts[rowNum] = newRow parts[rowNum] = newRow
} }
@ -69,7 +58,25 @@ class Day15: Runnable {
lastRow = parts.count - 1 lastRow = parts.count - 1
lastCol = (parts.first?.count ?? 0) - 1 lastCol = (parts.first?.count ?? 0) - 1
}
public func run() {
let input = try! String(contentsOfFile: inputPath)
parts = input
.trimmingCharacters(in: .newlines)
.components(separatedBy: .newlines)
.map { Array($0) }
.map { ar in ar.map {c in ThreatLevel(c.description)!} }
lastRow = parts.count - 1
lastCol = (parts.first?.count ?? 0) - 1
calculateSafestPath()
expandMap()
neighbors = [Coord: [Coord]]()
calculateSafestPath()
}
private func calculateSafestPath() {
// Distances to startNode // Distances to startNode
var totalThreatLevel = [Coord: ThreatLevel]() var totalThreatLevel = [Coord: ThreatLevel]()
@ -78,6 +85,13 @@ class Day15: Runnable {
Coord(row: row.offset, col: col) Coord(row: row.offset, col: col)
} }
}) })
/* Keep a seperate dictionary, to calculate which coordinates have a set threat level
* a.k.a total distance to start
* This allows to find the next coordinate to check fairly quickly, by just
* looking at the minmum key in this.
* I initially tried a PriorityQueue, but my implementation was pretty slow and it spent too much time sorting
*/
var threatLevelDistrubution = [ThreatLevel: Set<Coord>]() var threatLevelDistrubution = [ThreatLevel: Set<Coord>]()
let startNode = Coord(row: 0, col: 0) let startNode = Coord(row: 0, col: 0)
totalThreatLevel[startNode] = 0 totalThreatLevel[startNode] = 0
@ -89,6 +103,8 @@ class Day15: Runnable {
let currentNode = threatLevelDistrubution[threatLevel]!.first! let currentNode = threatLevelDistrubution[threatLevel]!.first!
unvisited.remove(currentNode) unvisited.remove(currentNode)
threatLevelDistrubution[threatLevel]!.remove(currentNode) threatLevelDistrubution[threatLevel]!.remove(currentNode)
// Remove key from dictionary if not coords are left for a specific threat level
if threatLevelDistrubution[threatLevel]!.isEmpty { if threatLevelDistrubution[threatLevel]!.isEmpty {
threatLevelDistrubution.removeValue(forKey: threatLevel) threatLevelDistrubution.removeValue(forKey: threatLevel)
} }
@ -114,6 +130,8 @@ class Day15: Runnable {
totalThreatLevel[a] = testCost totalThreatLevel[a] = testCost
threatLevelDistrubution[currentCost]!.remove(a) threatLevelDistrubution[currentCost]!.remove(a)
threatLevelDistrubution[testCost, default: Set<Coord>()].insert(a) threatLevelDistrubution[testCost, default: Set<Coord>()].insert(a)
// Remove key from dictionary if not coords are left for a specific threat leveli
if threatLevelDistrubution[currentCost]!.isEmpty { if threatLevelDistrubution[currentCost]!.isEmpty {
threatLevelDistrubution.removeValue(forKey: currentCost) threatLevelDistrubution.removeValue(forKey: currentCost)
} }