From b8fda3862dba1a24276e50b3899a95297a5a16af Mon Sep 17 00:00:00 2001 From: Sven Weidauer Date: Sat, 17 Dec 2022 17:38:00 +0100 Subject: [PATCH] 2022 Day 16 Part 1 --- 2022/day16.swift | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 2022/day16.swift diff --git a/2022/day16.swift b/2022/day16.swift new file mode 100644 index 0000000..9aaa2d4 --- /dev/null +++ b/2022/day16.swift @@ -0,0 +1,73 @@ +import Foundation +import RegexBuilder + +struct Room { + var name: String + var flowRate: Int + var connections: [String] +} + + +let regex = #/Valve (?[A-Z]{2}) has flow rate=(?\d+); tunnels? leads? to valves? (?[A-Z]{2}(, [A-Z]{2})*)/# + +var rooms: [String: Room] = [:] + +for try await line in URL(fileURLWithPath: "day16.input").lines { + guard let match = try regex.wholeMatch(in: line) else { + fatalError("Invalid input: \(line)") + } + + rooms[String(match.room)] = Room(name: String(match.room), flowRate: Int(match.flow)!, connections: match.links.split(separator: ", ").map(String.init)) +} + + +struct Path { + var rooms: [String] = [] + var opened: Set = [] + var pressure: Int = 0 +} + +let totalTime = 30 + +func findPath(from room: Room, previous: String? = nil, time: Int = totalTime, path: inout Path) { + guard time > 0 else { return } + + let best = findBest(path: path, room: room, previous: previous, turnedOn: false, time: time - 1) + + if time >= 2, room.flowRate > 0 && path.opened.insert(room.name).inserted { + path.pressure += (time - 1) * room.flowRate + path = findBest(path: path, room: room, previous: previous, turnedOn: true, time: time - 2) + } + + if best.pressure > path.pressure { + path = best + } +} + +func findBest(path: Path, room: Room, previous: String? = nil, turnedOn: Bool, time: Int) -> Path { + var path = path + path.rooms.append("\(room.name)[\(room.flowRate)]\(turnedOn ? "*" : "")") + + var best = path + + for next in room.connections { + if !turnedOn && previous == next { + continue + } + + let nextRoom = rooms[next]! + + var nextPath = path + findPath(from: nextRoom, previous: room.name, time: time, path: &nextPath) + if nextPath.pressure > best.pressure { + best = nextPath + } + } + + return best +} + +var path = Path() +findPath(from: rooms["AA"]!, path: &path) +print(path.rooms) +print(path.pressure) \ No newline at end of file