Advertisement
Guest User

Untitled

a guest
Dec 16th, 2022
737
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.98 KB | None | 0 0
  1. from dataclasses import dataclass
  2. from copy import copy
  3.  
  4. INPUT_FILENAME = "Day 16/input_1.txt"
  5. INF = int(1e9)
  6.  
  7.  
  8. @dataclass
  9. class Valve:
  10.     name: str
  11.     flow_rate: int
  12.     children: list[str]
  13.  
  14.  
  15. def parse_input():
  16.     with open(INPUT_FILENAME, "r") as file:
  17.         lines = [l.rstrip() for l in file.readlines()]
  18.  
  19.     valves = {}
  20.  
  21.     for line in lines:
  22.         split = line.split(" ")
  23.         valve_name = split[1]
  24.         flow_rate = int(split[4][:-1].split("=")[1])
  25.         children = [split[-1]] + [token[:-1] for token in split if token.endswith(",")]
  26.         valves[valve_name] = Valve(valve_name, flow_rate, children)
  27.  
  28.     return valves
  29.  
  30.  
  31. def floid_warshall(valves):
  32.     dist = {v: {u: INF for u in valves} for v in valves}
  33.  
  34.     for v in valves:
  35.         dist[v][v] = 0
  36.         for u in valves[v].children:
  37.             dist[v][u] = 1
  38.  
  39.     for k in valves:
  40.         for i in valves:
  41.             for j in valves:
  42.                 dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
  43.  
  44.     return dist
  45.  
  46.  
  47. def main():
  48.     valves = parse_input()
  49.     distances = floid_warshall(valves)
  50.     non_zero_valves = [v for v in valves if valves[v].flow_rate > 0]
  51.  
  52.     def generate_open_options(pos, open_valves, time_left):
  53.         for next in non_zero_valves:
  54.             if next not in open_valves and distances[pos][next] < time_left:
  55.                 open_valves.append(next)
  56.                 yield from generate_open_options(
  57.                     next, open_valves, time_left - distances[pos][next] - 1
  58.                 )
  59.                 open_valves.pop()
  60.  
  61.         yield copy(open_valves)
  62.  
  63.     def get_order_score(open_order, time_left):
  64.         now, ans = "AA", 0
  65.         for pos in open_order:
  66.             time_left -= distances[now][pos] + 1
  67.             ans += valves[pos].flow_rate * time_left
  68.             now = pos
  69.         return ans
  70.  
  71.     def solution_1():
  72.         return max(get_order_score(o, 30) for o in generate_open_options("AA", [], 30))
  73.  
  74.     def solution_2():
  75.         ways = list(generate_open_options("AA", [], 26))
  76.  
  77.         best_scores = {}
  78.  
  79.         for order in ways:
  80.             tup = tuple(sorted(order))
  81.             score = get_order_score(order, 26)
  82.             best_scores[tup] = max(best_scores.get(tup, 0), score)
  83.  
  84.         best_scores = list(best_scores.items())
  85.        
  86.         print(len(best_scores))
  87.         print(len(ways))
  88.  
  89.         ans = 0
  90.         for human_idx in range(len(best_scores)):
  91.             for elephant_idx in range(human_idx + 1, len(best_scores)):
  92.                 human_opens, human_score = best_scores[human_idx]
  93.                 elephant_opens, elephant_score = best_scores[elephant_idx]
  94.  
  95.                 if len(set(human_opens).intersection(elephant_opens)) == 0:
  96.                     ans = max(ans, human_score + elephant_score)
  97.  
  98.         return ans
  99.  
  100.     print("Answer 1:", solution_1())
  101.     print("Answer 2:", solution_2())
  102.  
  103.  
  104. if __name__ == "__main__":
  105.     # INPUT_FILENAME = "Day 16/sample.txt"
  106.     main()
  107.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement