Advertisement
Guest User

Untitled

a guest
Dec 18th, 2023
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.47 KB | Source Code | 0 0
  1. from dataclasses import dataclass
  2.  
  3. @dataclass
  4. class Beam:
  5.     i : int
  6.     j : int
  7.     direction : str
  8.  
  9.  
  10. def move(beam):
  11.     if beam.direction == "N": beam.i -= 1
  12.     if beam.direction == "W": beam.j -= 1
  13.     if beam.direction == "S": beam.i += 1
  14.     if beam.direction == "E": beam.j += 1
  15.  
  16. def beam_advance(beam):
  17.     global beams_todo
  18.     global beams_done
  19.     global exits
  20.  
  21.     # beam being explored, remove from todo
  22.     beams_todo.pop(0)
  23.  
  24.     # move beam in its direction
  25.     move(beam)
  26.    
  27.     i = beam.i
  28.     j = beam.j
  29.     direction = beam.direction
  30.    
  31.     if i < 0 or j < 0 or i >= len(lines) or j >= len(lines[0]):
  32.         # OOB/out of grid
  33.         # print("oob")
  34.         # exit reached, reverse the direction to remember to remove this start later
  35.         if   direction == "N": rev_dir = "S"
  36.         elif direction == "W": rev_dir = "E"
  37.         elif direction == "S": rev_dir = "N"
  38.         elif direction == "E": rev_dir = "W"
  39.         exits.append(Beam(i, j, rev_dir))
  40.         return
  41.  
  42.     if beam in beams_done:
  43.         # already explored this beam on this tile and direction, skip
  44.         # print(beam, "done")
  45.         return
  46.  
  47.     # add to explored beams
  48.     beams_done.append(beam)
  49.  
  50.     # explore
  51.     char = lines[i][j]
  52.    
  53.     if char == ".":
  54.         beams_todo.append(Beam(i, j, direction))
  55.  
  56.     elif char == "/":
  57.         if   direction == "N": beams_todo.append(Beam(i, j, "E"))
  58.         elif direction == "W": beams_todo.append(Beam(i, j, "S"))
  59.         elif direction == "S": beams_todo.append(Beam(i, j, "W"))
  60.         elif direction == "E": beams_todo.append(Beam(i, j, "N"))
  61.  
  62.     elif char == "\\":
  63.         if   direction == "N": beams_todo.append(Beam(i, j, "W"))
  64.         elif direction == "W": beams_todo.append(Beam(i, j, "N"))
  65.         elif direction == "S": beams_todo.append(Beam(i, j, "E"))
  66.         elif direction == "E": beams_todo.append(Beam(i, j, "S"))
  67.  
  68.     elif char == "|":
  69.         if   direction in "NS":
  70.             beams_todo.append(Beam(i, j, direction))
  71.         elif direction in "WE":
  72.             beams_todo.append(Beam(i, j, "N"))
  73.             beams_todo.append(Beam(i, j, "S"))
  74.  
  75.     elif char == "-":
  76.         if   direction in "WE":
  77.             beams_todo.append(Beam(i, j, direction))
  78.         elif direction in "NS":
  79.             beams_todo.append(Beam(i, j, "W"))
  80.             beams_todo.append(Beam(i, j, "E"))
  81.  
  82. # script start
  83. with open("input.txt", "r") as f:
  84.     lines = f.readlines()
  85.  
  86. lines = [l.replace("\n", "") for l in lines]
  87. best_energized = 0
  88.  
  89. # starts to explore
  90. starts_todo = []
  91. for i in range(len(lines)):
  92.     starts_todo.append(Beam(i, -1, "E"))
  93.     starts_todo.append(Beam(i, len(lines[0]), "W"))
  94. for j in range(len(lines[0])):
  95.     starts_todo.append(Beam(-1, j, "S"))
  96.     starts_todo.append(Beam(len(lines), j, "N"))
  97.  
  98. while starts_todo:
  99.     beams_todo = [] # list of beams to explore with the current start
  100.     beams_done = [] # list of beams explored with the current start
  101.     energized = []
  102.     exits = [] # exits reached with the current start
  103.  
  104.     beams_todo.append(starts_todo[0])
  105.  
  106.     while beams_todo:
  107.         beam_advance(beams_todo[0])
  108.    
  109.     print(starts_todo[0], "done, remaining:", len(starts_todo), "/ 440")
  110.     starts_todo.pop(0)
  111.  
  112.     # all exits reached by the start are at best equal, so they can be safely not explored
  113.     for exit in exits:
  114.         # remove 1 by 1 because of potential issues with pop indexes
  115.         for x, start in enumerate(starts_todo):
  116.             if exit == start:
  117.                 print(starts_todo[x], "pop, remaining:", len(starts_todo), "/ 440")
  118.                 starts_todo.pop(x)
  119.  
  120.     print(len(beams_done))
  121.  
  122.     for e in beams_done:
  123.         if (e.i, e.j) not in energized:
  124.             energized.append((e.i, e.j))
  125.  
  126.     print(len(energized))
  127.     if len(energized) > best_energized:
  128.         best_energized = len(energized)
  129.  
  130. print(f"{best_energized=}")
  131.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement