12a
This commit is contained in:
111
Sources/12/12.swift
Normal file
111
Sources/12/12.swift
Normal file
@ -0,0 +1,111 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Max Nuding on 12.12.21.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Runner
|
||||
import Collections
|
||||
|
||||
class Cave: Hashable, CustomStringConvertible, CustomDebugStringConvertible {
|
||||
static func == (lhs: Cave, rhs: Cave) -> Bool { lhs.name == rhs.name }
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(name)
|
||||
}
|
||||
|
||||
var description: String { name }
|
||||
var debugDescription: String { name }
|
||||
|
||||
let name: String
|
||||
var connectedCaves = [Cave]()
|
||||
var isBigCave: Bool
|
||||
var isEnd: Bool
|
||||
|
||||
required init(name: String) {
|
||||
self.name = name
|
||||
self.isBigCave = name.first!.isUppercase
|
||||
self.isEnd = name == "end"
|
||||
}
|
||||
}
|
||||
|
||||
class Path: Hashable, CustomStringConvertible {
|
||||
static func == (lhs: Path, rhs: Path) -> Bool {
|
||||
lhs.parts == rhs.parts
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(parts)
|
||||
}
|
||||
|
||||
var parts: [Cave]
|
||||
private var partsSet: Set<Cave>
|
||||
var description: String { parts.map {$0.description}.joined(separator: "->") }
|
||||
|
||||
required init(parts: [Cave]) {
|
||||
self.parts = parts
|
||||
partsSet = Set(parts)
|
||||
}
|
||||
|
||||
func contains(cave: Cave) -> Bool { partsSet.contains(cave) }
|
||||
}
|
||||
|
||||
class Day12: Runnable {
|
||||
let inputPath: String
|
||||
var caves = [String:Cave]()
|
||||
|
||||
required init(inputPath: String) {
|
||||
self.inputPath = inputPath
|
||||
}
|
||||
|
||||
public func run() {
|
||||
let input = try! String(contentsOfFile: inputPath)
|
||||
caves = input
|
||||
.trimmingCharacters(in: .newlines)
|
||||
.components(separatedBy: .newlines)
|
||||
.reduce(into: [String:Cave](), { caves, line in
|
||||
let caveConnection = line.components(separatedBy: "-")
|
||||
let caveFromName = caveConnection.first!
|
||||
let caveToName = caveConnection.last!
|
||||
let from = caves[caveFromName] ?? Cave(name: caveFromName)
|
||||
let to = caves[caveToName] ?? Cave(name: caveToName)
|
||||
from.connectedCaves.append(to)
|
||||
to.connectedCaves.append(from)
|
||||
caves[caveFromName] = from
|
||||
caves[caveToName] = to
|
||||
|
||||
})
|
||||
|
||||
var queue = Deque<Path>(minimumCapacity: 10000)
|
||||
var visited = Set<Path>(minimumCapacity: 10000)
|
||||
var numFinished = 0
|
||||
|
||||
var cave: Path? = Path(parts: [caves["start"]!])
|
||||
queue.append(cave!)
|
||||
|
||||
while !queue.isEmpty {
|
||||
cave = queue.popFirst()
|
||||
if visited.contains(cave!) {
|
||||
continue
|
||||
}
|
||||
//print("Current path: \(cave!)")
|
||||
visited.insert(cave!)
|
||||
|
||||
cave!.parts.last!.connectedCaves
|
||||
.filter { $0.isBigCave || !cave!.contains(cave: $0) }
|
||||
.forEach {
|
||||
if $0.isEnd {
|
||||
numFinished += 1
|
||||
//print("Finished: \(cave!.parts)->end")
|
||||
return
|
||||
}
|
||||
var newParts = cave!.parts
|
||||
newParts.append($0)
|
||||
queue.append(Path(parts: newParts))
|
||||
}
|
||||
}
|
||||
print(numFinished)
|
||||
}
|
||||
}
|
12
Sources/12/main.swift
Normal file
12
Sources/12/main.swift
Normal file
@ -0,0 +1,12 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Max Nuding on 05.12.21.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Runner
|
||||
|
||||
//Runner(target: Day12.self, day: "12", isTest: true).run()
|
||||
Runner(target: Day12.self, day: "12", isTest: false).run()
|
Reference in New Issue
Block a user