This commit is contained in:
Max Nuding 2021-12-12 10:43:05 +01:00
parent 5052110cb1
commit 7f201a614b
Signed by: phlaym
GPG Key ID: A06651BAB6777237
2 changed files with 64 additions and 23 deletions

View File

@ -23,33 +23,42 @@ class Cave: Hashable, CustomStringConvertible, CustomDebugStringConvertible {
var connectedCaves = [Cave]() var connectedCaves = [Cave]()
var isBigCave: Bool var isBigCave: Bool
var isEnd: Bool var isEnd: Bool
var isStart: Bool
required init(name: String) { required init(name: String) {
self.name = name self.name = name
self.isBigCave = name.first!.isUppercase self.isBigCave = name.first!.isUppercase
self.isEnd = name == "end" self.isEnd = name == "end"
self.isStart = name == "start"
} }
} }
class Path: Hashable, CustomStringConvertible { struct Path: Hashable, CustomStringConvertible {
static func == (lhs: Path, rhs: Path) -> Bool { var parts: [Cave]
lhs.parts == rhs.parts var visitedSmallCaveTwice = false
var description: String
func contains(cave: Cave) -> Bool { parts.contains(cave) }
func appending(cave: Cave) -> Path {
var newParts = parts
newParts.append(cave)
return Path(
parts: newParts,
visitedSmallCaveTwice: visitedSmallCaveTwice || !cave.isBigCave && contains(cave: cave))
} }
static func == (lhs: Path, rhs: Path) -> Bool { lhs.description == rhs.description }
func hash(into hasher: inout Hasher) { func hash(into hasher: inout Hasher) {
hasher.combine(parts) hasher.combine(description)
} }
var parts: [Cave] init(parts: [Cave], visitedSmallCaveTwice: Bool = false) {
private var partsSet: Set<Cave>
var description: String { parts.map {$0.description}.joined(separator: "->") }
required init(parts: [Cave]) {
self.parts = parts self.parts = parts
partsSet = Set(parts) self.visitedSmallCaveTwice = visitedSmallCaveTwice
self.description = (visitedSmallCaveTwice ? "*" : "") + parts.map {$0.description}.joined(separator: "->")
} }
func contains(cave: Cave) -> Bool { partsSet.contains(cave) }
} }
class Day12: Runnable { class Day12: Runnable {
@ -77,7 +86,12 @@ class Day12: Runnable {
caves[caveToName] = to caves[caveToName] = to
}) })
runA()
runB()
}
func runA() {
var queue = Deque<Path>(minimumCapacity: 10000) var queue = Deque<Path>(minimumCapacity: 10000)
var visited = Set<Path>(minimumCapacity: 10000) var visited = Set<Path>(minimumCapacity: 10000)
var numFinished = 0 var numFinished = 0
@ -90,7 +104,6 @@ class Day12: Runnable {
if visited.contains(cave!) { if visited.contains(cave!) {
continue continue
} }
//print("Current path: \(cave!)")
visited.insert(cave!) visited.insert(cave!)
cave!.parts.last!.connectedCaves cave!.parts.last!.connectedCaves
@ -108,4 +121,35 @@ class Day12: Runnable {
} }
print(numFinished) print(numFinished)
} }
func runB() {
var queue = Deque<Path>(minimumCapacity: 1000000)
var visited = Set<Path>(minimumCapacity: 1000000)
var numFinished = 0
var cave: Path? = Path(parts: [caves["start"]!])
queue.append(cave!)
while !queue.isEmpty {
cave = queue.popFirst()
if visited.contains(cave!) {
continue
}
visited.insert(cave!)
cave!.parts.last!.connectedCaves
.forEach {
if $0.isStart || (cave!.visitedSmallCaveTwice && !$0.isBigCave && cave!.contains(cave: $0)) {
return
}
if $0.isEnd {
numFinished += 1
return
}
var newParts = cave!.parts
newParts.append($0)
queue.append(cave!.appending(cave: $0))
}
}
print(numFinished)
}
} }

View File

@ -1,10 +1,7 @@
dc-end start-A
HN-start start-b
start-kj A-c
dc-start A-b
dc-HN b-d
LN-dc A-end
HN-end b-end
kj-sa
kj-HN
kj-dc