Advertisement
illuminati229

AoC 202 Day 16

Dec 16th, 2022
1,275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.88 KB | None | 0 0
  1. from time import time
  2. import networkx as nx
  3. import matplotlib.pyplot as plt
  4. from copy import copy
  5. from itertools import combinations
  6.  
  7.  
  8. def timer_func(func):
  9.     # This function shows the execution time of
  10.     # the function object passed
  11.     def wrap_func(*args, **kwargs):
  12.         t1 = time()
  13.         result = func(*args, **kwargs)
  14.         t2 = time()
  15.         print(f'Function {func.__name__!r} executed in {(t2 - t1):.4f}s')
  16.         return result
  17.  
  18.     return wrap_func
  19.  
  20.  
  21. class Cave:
  22.     def __init__(self, name, flow, connected):
  23.         self.name = name
  24.         self.flow = flow
  25.         self.connected = connected
  26.         self.valve_connect = {}  # path length to caves with valves that can flow
  27.  
  28.     def __str__(self):
  29.         return f'Cave {self.name}'
  30.  
  31.     def __repr__(self):
  32.         return f'Cave {self.name}'
  33.  
  34.  
  35. def cave_search(start, path, time_rem, flow, valid_paths):
  36.     for cave in start.valve_connect:
  37.         if cave in path or cave == start:
  38.             continue
  39.         elif time_rem - start.valve_connect[cave] <= 0:
  40.             continue
  41.         else:
  42.             new_time_rem = time_rem - start.valve_connect[cave]
  43.             new_flow = flow + new_time_rem * cave.flow
  44.             valid_paths[path + tuple([cave])] = {'time': new_time_rem, 'flow': new_flow}
  45.             valid_paths = cave_search(cave, path + tuple([cave]), new_time_rem, new_flow, valid_paths)
  46.     return valid_paths
  47.  
  48. @timer_func
  49. def day16(filepath, part2=False):
  50.     with open(filepath) as fin:
  51.         lines = fin.readlines()
  52.  
  53.     caves = []
  54.     closed_valves = []
  55.  
  56.     for line in lines:
  57.         cave = line.split()[1]
  58.         flow_rate = int(line.split('=')[-1].split(';')[0])
  59.         if 'valves' in line:
  60.             connected_caves = [entry.strip() for entry in line.split('lead to valves')[-1].split(',')]
  61.         else:
  62.             connected_caves = [line.split('leads to valve')[-1].strip()]
  63.         caves.append(Cave(cave, flow_rate, connected_caves))
  64.         if caves[-1].flow > 0:
  65.             closed_valves.append(caves[-1])
  66.         if caves[-1].name == 'AA':
  67.             start = caves[-1]
  68.  
  69.     G = nx.Graph()
  70.     for cave in caves:
  71.         for c_cave in cave.connected:
  72.             for cave1 in caves:
  73.                 if cave1.name == c_cave:
  74.                     v = cave1
  75.                     break
  76.             G.add_edge(cave, v)
  77.  
  78.     for cave in closed_valves:
  79.         start.valve_connect[cave] = len(nx.shortest_path(G, start, cave))
  80.         for cave1 in closed_valves:
  81.             if cave1 != cave:
  82.                 cave.valve_connect[cave1] = len(nx.shortest_path(G, cave, cave1))
  83.  
  84.     valid_paths = cave_search(start, (), 30, 0, {})
  85.  
  86.     max_flow = max([val['flow'] for val in valid_paths.values()])
  87.     print(f'Part 1: {max_flow}')
  88.  
  89.     closed_valves_len = len(closed_valves)
  90.     new_valid_paths = {}
  91.     for key, value in valid_paths.items():
  92.         if value['time'] > 4:
  93.             new_valid_paths[key] = value
  94.     flows = []
  95.     for a, b in combinations(new_valid_paths, 2):
  96.         if len(set(a).intersection(b)) > 0:
  97.             continue
  98.         else:
  99.             time_rem = 26 - start.valve_connect[a[0]]
  100.             a_flow = a[0].flow*time_rem
  101.             if len(a) > 1:
  102.                 for i, entry in enumerate(a[1:]):
  103.                     time_rem = time_rem - a[i].valve_connect[entry]
  104.                     a_flow += time_rem * entry.flow
  105.             time_rem = 26 - start.valve_connect[b[0]]
  106.             b_flow = b[0].flow * time_rem
  107.             if len(b) > 1:
  108.                 for i, entry in enumerate(b[1:]):
  109.                     time_rem = time_rem - b[i].valve_connect[entry]
  110.                     b_flow += time_rem * entry.flow
  111.  
  112.             flows.append(a_flow + b_flow)
  113.  
  114.     max_flow = max(flows)
  115.     print(f'Part 2: {max_flow}')
  116.  
  117.  
  118. def main():
  119.     day16('test16')
  120.  
  121.     day16('input16')
  122.  
  123.  
  124. if __name__ == '__main__':
  125.     main()
  126.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement