// // File.swift // // // Created by Max Nuding on 15s.12.21. // import Foundation import Runner import Collections typealias ThreatLevel = Int struct Coord: Hashable, CustomStringConvertible { let row: Int let col: Int var description: String { "(\(row), \(col))" } func neighbors() -> [Coord] { [ Coord(row: row-1, col: col), Coord(row: row, col: col+1), Coord(row: row+1, col: col), Coord(row: row, col: col-1) ] } } class Day15: Runnable { let inputPath: String var field = [Coord]() var lastRow: Int = 0 var lastCol: Int = 0 var parts = [[ThreatLevel]]() var neighbors = [Coord: [Coord]]() required init(inputPath: String) { self.inputPath = inputPath } 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 var unvisited = Set() // Distances to startNode var totalThreatLevel = [Coord: ThreatLevel]() for row in parts.enumerated() { for col in row.element.indices { let c = Coord(row: row.offset, col: col) unvisited.insert(c) //totalThreatLevel[c] = Int.max } } let startNode = Coord(row: 0, col: 0) totalThreatLevel[startNode] = 0 while let currentNode = unvisited.min(by: { totalThreatLevel[$0, default: Int.max] < totalThreatLevel[$1, default: Int.max] }) { //var currentNode = ! unvisited.remove(currentNode) if neighbors[currentNode] == nil { neighbors[currentNode] = currentNode .neighbors() .filter { $0.col >= 0 && $0.col <= lastCol && $0.row >= 0 && $0.row <= lastRow } } var adjacent = neighbors[currentNode]! neighbors[currentNode] = adjacent adjacent = adjacent .filter { unvisited.contains($0) } let currentThreatLevel = totalThreatLevel[currentNode, default: Int.max] for a in adjacent { let testCost = parts[a] + currentThreatLevel if totalThreatLevel[a, default: Int.max] > testCost { totalThreatLevel[a] = testCost } } } print(totalThreatLevel[Coord(row: lastRow, col: lastCol)]!) } } extension Array where Element == Array { subscript(coord: Coord) -> Int { get { self[coord.row][coord.col] } set(newValue) { self[coord.row][coord.col] = newValue } } }