From 7f201a614b95f52b0800f70a615d580b5ce4c7c4 Mon Sep 17 00:00:00 2001 From: Max Nuding Date: Sun, 12 Dec 2021 10:43:05 +0100 Subject: [PATCH] 12b --- Sources/12/12.swift | 70 ++++++++++++++++++---- Sources/Runner/Resources/input/12_test.txt | 17 +++--- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/Sources/12/12.swift b/Sources/12/12.swift index 668e9b5..5bf2e85 100644 --- a/Sources/12/12.swift +++ b/Sources/12/12.swift @@ -23,33 +23,42 @@ class Cave: Hashable, CustomStringConvertible, CustomDebugStringConvertible { var connectedCaves = [Cave]() var isBigCave: Bool var isEnd: Bool + var isStart: Bool required init(name: String) { self.name = name self.isBigCave = name.first!.isUppercase self.isEnd = name == "end" + self.isStart = name == "start" } } -class Path: Hashable, CustomStringConvertible { - static func == (lhs: Path, rhs: Path) -> Bool { - lhs.parts == rhs.parts +struct Path: Hashable, CustomStringConvertible { + var parts: [Cave] + 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) { - hasher.combine(parts) + hasher.combine(description) } - var parts: [Cave] - private var partsSet: Set - var description: String { parts.map {$0.description}.joined(separator: "->") } - - required init(parts: [Cave]) { + init(parts: [Cave], visitedSmallCaveTwice: Bool = false) { 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 { @@ -77,7 +86,12 @@ class Day12: Runnable { caves[caveToName] = to }) + runA() + runB() + } + + func runA() { var queue = Deque(minimumCapacity: 10000) var visited = Set(minimumCapacity: 10000) var numFinished = 0 @@ -90,7 +104,6 @@ class Day12: Runnable { if visited.contains(cave!) { continue } - //print("Current path: \(cave!)") visited.insert(cave!) cave!.parts.last!.connectedCaves @@ -108,4 +121,35 @@ class Day12: Runnable { } print(numFinished) } + + func runB() { + var queue = Deque(minimumCapacity: 1000000) + var visited = Set(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) + } } diff --git a/Sources/Runner/Resources/input/12_test.txt b/Sources/Runner/Resources/input/12_test.txt index 62cc714..6fd8c41 100644 --- a/Sources/Runner/Resources/input/12_test.txt +++ b/Sources/Runner/Resources/input/12_test.txt @@ -1,10 +1,7 @@ -dc-end -HN-start -start-kj -dc-start -dc-HN -LN-dc -HN-end -kj-sa -kj-HN -kj-dc +start-A +start-b +A-c +A-b +b-d +A-end +b-end