From a0192880a37069b60604b25419f943e2df221309 Mon Sep 17 00:00:00 2001 From: Luna Lailatova Date: Sat, 24 Dec 2022 23:42:11 +0100 Subject: [PATCH] hhhhhhhhhhhhhhhhhhhhhhhhh --- day16-2.py | 154 +++++++++++++++++++++++++++++------------------- day16-2take2.py | 101 ++++++++++++++++++------------- 2 files changed, 155 insertions(+), 100 deletions(-) diff --git a/day16-2.py b/day16-2.py index 98d6e57..36d4fd0 100644 --- a/day16-2.py +++ b/day16-2.py @@ -1,11 +1,13 @@ -import queue +import queue -q = queue.Queue() +MAX_STEPS = 26 + +q = queue.PriorityQueue() valves = {} valvesConsider = {} -destinationQue = queue.Queue() -shortest = None distanceMap = {} +eliminated = {} +numTotalSteps = 0 class Valve(): def __init__(self, flowRate, tunnels, name): @@ -16,25 +18,71 @@ class Valve(): def getFlowrate(self): return self.flowRate - def moves(self, destination, length): - global shortest - if shortest is not None and length >= shortest: - return - if self.name == destination: - if shortest is None or length <= shortest: - shortest = length - return - _length = length + 1 - for val in self.tunnels: - destinationQue.put((val, destination, _length)) + def genDistanceMap(self): + nextValves = queue.PriorityQueue() + nextValves.put((0, self)) + + distanceMap[(self.name, self.name)] = 0 + + while not nextValves.empty(): + curDist, valve = nextValves.get() + + for tunnel in valve.tunnels: + if (self.name, tunnel) in distanceMap: + continue + + nextValve = valves[tunnel] + nextDist = curDist + 1 + + distanceMap[(self.name, nextValve.name)] = nextDist + nextValves.put((nextDist, nextValve)) + + def __lt__(self, other): + return self.flowRate < other.flowRate and self.name < other.name + + +def maxRemaining(remainingTime, possibleValves): + nextSteps = [2 * x for x in range(int(remainingTime / 2) + 1)] + + allValveValues = list(reversed([v for _, v in possibleValves.items()])) + possibleRemaining = 0 + + for timeOffset in nextSteps: + if timeOffset > remainingTime: + break + + if len(allValveValues) == 0: + break + + openFor = remainingTime - timeOffset + possibleRemaining += allValveValues[0] * (remainingTime - timeOffset) + allValveValues = allValveValues[1:] + + if len(allValveValues) == 0: + break + + possibleRemaining += allValveValues[0] * (remainingTime - timeOffset) + allValveValues = allValveValues[1:] + + return possibleRemaining def step(position1, position2, busy1, busy2, currentTime, pressure, _valvesCons): global curentbest + global numTotalSteps + global maxRemaining + + numTotalSteps += 1 + + if maxRemaining(MAX_STEPS - currentTime, _valvesCons) + pressure < curentbest: + # There's no way we can get better than the current max pressure, so bail. + eliminated.setdefault('maxRemaining', 0) + eliminated['maxRemaining'] += 1 + return + done = False if pressure > curentbest: - print(1) curentbest = pressure if len(_valvesCons) == 0: return @@ -42,46 +90,44 @@ def step(position1, position2, busy1, busy2, currentTime, pressure, _valvesCons) for destination in _valvesCons: _CopyCons = _valvesCons.copy() _dist = distanceMap[(position1, destination)] - if (currentTime + _dist + 1) >= 26: + if (currentTime + _dist + 1) >= MAX_STEPS: continue - _busy1 =_dist + 1 - _pressure = pressure + ((26 - currentTime - _busy1)* _CopyCons[destination]) + _busy1 = _dist + 1 + _pressure = pressure + ((MAX_STEPS - currentTime - _busy1) * _CopyCons[destination]) _CopyCons.pop(destination) done = True - q.put((destination, position2, _busy1, busy2, currentTime, _pressure, _CopyCons)) + q.put((_pressure * -1, destination, position2, _busy1, busy2, currentTime, _CopyCons)) if done: return if busy2 == 0: for destination in _valvesCons: _CopyCons = _valvesCons.copy() _dist = distanceMap[(position2, destination)] - if (currentTime + _dist + 1) >= 26: + if (currentTime + _dist + 1) >= MAX_STEPS: continue _busy2 =_dist + 1 - _pressure = pressure + ((26 - currentTime - _busy2)* _CopyCons[destination]) + _pressure = pressure + ((MAX_STEPS - currentTime - _busy2)* _CopyCons[destination]) _CopyCons.pop(destination) - q.put((position1, destination, busy1, _busy2, currentTime, _pressure, _CopyCons)) + done = True + q.put((_pressure * -1, position1, destination, busy1, _busy2, currentTime, _CopyCons)) + if done: + return + if busy1 <= 0 and busy2 <= 0: return - _currentTime = currentTime + 1 - _busy1 = busy1 - 1 - _busy2 = busy2 - 1 + elif busy2 == 0: + idle = busy1 + elif busy1 == 0: + idle = busy2 + else: + idle = min(busy1, busy2) + _currentTime = currentTime + idle + _busy1 = busy1 - idle + _busy2 = busy2 - idle _CopyCons = _valvesCons.copy() - if _currentTime >= 26: + if _currentTime >= MAX_STEPS: return - q.put((position1, position2, _busy1, _busy2, _currentTime, pressure, _CopyCons)) - - - - -def distance(position, destination): - global destinationQue - global shortest - shortest = None - destinationQue.put((position, destination, 0)) - while not destinationQue.empty(): - _position, _destination, length = destinationQue.get() - valves[_position].moves(_destination, length) - return shortest + q.put((pressure * -1, position1, position2, _busy1, _busy2, _currentTime, _CopyCons)) + openvalves = [] @@ -103,21 +149,8 @@ for line in inp: newValve = Valve( flowRate, tunnels, _valve) valves[_valve] = newValve -n = 0 - -for start in valvesConsider: - n += 1 - distanceMap[('AA', start)] = distance('AA', start) - print(n) - for end in valvesConsider: - if (start, end) in distanceMap: - continue - n += 1 - _dist = distance(start, end) - distanceMap[(start, end)] = _dist - distanceMap[(end, start)] = _dist - print(n) - +for _, valve in valves.items(): + valve.genDistanceMap() for i in distanceMap: print(i, distanceMap[i]) @@ -126,12 +159,13 @@ position = 'AA' currentTime = 0 pressure = 0 curentbest = 0 -q.put((position, position, 0, 0, currentTime, pressure, valvesConsider)) +q.put((pressure, position, position, 0, 0, currentTime, valvesConsider)) while not q.empty(): - print(q.qsize()) - position1, position2, busy1, busy2, currentTime, pressure, _valvesConsider = q.get() - step(position1, position2, busy1, busy2, currentTime, pressure, _valvesConsider) + #print(q.qsize()) + pressure, position1, position2, busy1, busy2, currentTime, _valvesConsider = q.get() + # print(q.qsize(), pressure, position1, position2, busy1, busy2, currentTime, numTotalSteps, eliminated) + step(position1, position2, busy1, busy2, currentTime, pressure * -1, _valvesConsider) print(curentbest) diff --git a/day16-2take2.py b/day16-2take2.py index fa62769..ad99ba7 100644 --- a/day16-2take2.py +++ b/day16-2take2.py @@ -1,11 +1,23 @@ -import queue +import queue -q = queue.Queue() +MAX_STEPS = 26 + +q = queue.PriorityQueue() valves = {} valvesConsider = {} -destinationQue = queue.Queue() -shortest = None distanceMap = {} +visited = {} +this_is_n = 0 + +def print_every_n(*args): + global this_is_n + + if this_is_n >= 10000: + this_is_n = 0 + print(*args) + + this_is_n += 1 + class Valve(): def __init__(self, flowRate, tunnels, name): @@ -16,42 +28,64 @@ class Valve(): def getFlowrate(self): return self.flowRate - def moves(self, destination, length): - global shortest - if shortest is not None and length >= shortest: - return - if self.name == destination: - if shortest is None or length <= shortest: - shortest = length - return - _length = length + 1 - for val in self.tunnels: - destinationQue.put((val, destination, _length)) + def genDistanceMap(self): + nextValves = queue.PriorityQueue() + nextValves.put((0, self)) + + distanceMap[(self.name, self.name)] = 0 + + while not nextValves.empty(): + curDist, valve = nextValves.get() + for tunnel in valve.tunnels: + if (self.name, tunnel) in distanceMap: + continue + nextValve = valves[tunnel] + nextDist = curDist + 1 -def step(position, currentTime, pressure, _valvesCons, elephant): + distanceMap[(self.name, nextValve.name)] = nextDist + nextValves.put((nextDist, nextValve)) + + def __lt__(self, other): + return self.flowRate < other.flowRate and self.name < other.name + + +def step(position, currentTime, pressure, _valvesCons, elephant, path): global curentbest _pos = position best = None + if tuple(path) in visited: + return + visited[tuple(path)] = 1 for destination in _valvesCons: _elephant = elephant _openvalves = _valvesCons.copy() dist = distanceMap[(_pos, destination)] - value = (26 - currentTime - dist - 1) * _openvalves[destination] + value = (MAX_STEPS - currentTime - dist - 1) * _openvalves[destination] best = (destination, value , dist) _time = currentTime + best[2] + 1 - if _time >= 26: + if _time >= MAX_STEPS: if _elephant: continue - q.put(('AA', 0, pressure, _openvalves, True)) + _path = path.copy() + _path.append('AA') + q.put(pressure* -1,('AA', 0, pressure, _openvalves, True, _path)) continue _pressure = pressure + best[1] _position = best[0] _openvalves.pop(destination) - q.put((_position, _time, _pressure, _openvalves, elephant)) + _path = path.copy() + _path.append(destination) + q.put(_pressure * -1,(_position, _time, _pressure, _openvalves, elephant, _path)) if pressure > curentbest: curentbest = pressure + _openvalves = _valvesCons.copy() + + if not elephant: + _path = path.copy() + _path.append('AA') + q.put(pressure*-1 ,('AA', 0, pressure, _openvalves, True, _path)) def distance(position, destination): @@ -67,7 +101,7 @@ def distance(position, destination): openvalves = [] -with open('in.txt','r') as f: +with open('input16.txt','r') as f: inp = f.read().splitlines(keepends=False) for line in inp: @@ -84,21 +118,8 @@ for line in inp: newValve = Valve( flowRate, tunnels, _valve) valves[_valve] = newValve -n = 0 - -for start in valvesConsider: - n += 1 - distanceMap[('AA', start)] = distance('AA', start) - print(n) - for end in valvesConsider: - if (start, end) in distanceMap: - continue - n += 1 - _dist = distance(start, end) - distanceMap[(start, end)] = _dist - distanceMap[(end, start)] = _dist - print(n) - +for _, valve in valves.items(): + valve.genDistanceMap() for i in distanceMap: print(i, distanceMap[i]) @@ -107,12 +128,12 @@ position = 'AA' currentTime = 0 pressure = 0 curentbest = 0 -q.put((position, currentTime, pressure, valvesConsider, False)) +q.put(0, (position, currentTime, pressure, valvesConsider, False, [])) while not q.empty(): - print(q.qsize()) - position, currentTime, pressure, _valvesConsider, elephant = q.get() - step(position, currentTime, pressure, _valvesConsider, elephant) + print_every_n(q.qsize()) + position, currentTime, pressure, _valvesConsider, elephant, path = q.get() + step(position, currentTime, pressure, _valvesConsider, elephant, path) print(curentbest)