Advertisement
illuminati229

AoC 2022 Day 23

Jan 5th, 2023
1,648
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.13 KB | None | 0 0
  1. from time import time
  2. from collections import deque, Counter
  3.  
  4. CARD_DIR = {
  5.     'N': -1j,
  6.     'S': 1j,
  7.     'E': 1,
  8.     'W': -1,
  9. }
  10.  
  11.  
  12. def timer_func(func):
  13.     # This function shows the execution time of
  14.     # the function object passed
  15.     def wrap_func(*args, **kwargs):
  16.         t1 = time()
  17.         result = func(*args, **kwargs)
  18.         t2 = time()
  19.         print(f'Function {func.__name__!r} executed in {(t2 - t1):.4f}s')
  20.         return result
  21.  
  22.     return wrap_func
  23.  
  24.  
  25. def nearby(elf):
  26.     dirs = [-1-1j, 0-1j, 1-1j, -1, 1, -1+1j, 0+1j, 1+1j]
  27.     for d in dirs:
  28.         yield elf + d
  29.  
  30.  
  31. def look_around(elf, direction):
  32.     if direction == 'N':
  33.         dirs = [-1-1j, 0-1j, 1-1j]
  34.     elif direction == 'S':
  35.         dirs = [-1+1j, 0+1j, 1+1j]
  36.     elif direction == 'E':
  37.         dirs = [1-1j, 1, 1+1j]
  38.     else:  # direction == 'W':
  39.         dirs = [-1-1j, -1, -1+1j]
  40.  
  41.     for d in dirs:
  42.         yield elf + d
  43.  
  44.  
  45. def print_scan(elves):
  46.     elf_real = [int(elf.real) for elf in elves]
  47.     elf_imag = [int(elf.imag) for elf in elves]
  48.  
  49.     for y in range(min(elf_imag), max(elf_imag) + 1):
  50.         for x in range((min(elf_real)), max(elf_real) + 1):
  51.             if complex(x, y) in elves:
  52.                 print('#', end='')
  53.             else:
  54.                 print('.', end='')
  55.         print('')
  56.     print('')
  57.  
  58.  
  59. @timer_func
  60. def day23(filepath, part2=False):
  61.     with open(filepath) as fin:
  62.         lines = fin.readlines()
  63.  
  64.     elves = [complex(x, y) for y, line in enumerate(lines) for x, c in enumerate(line) if c == '#']
  65.  
  66.     # print_scan(elves)
  67.  
  68.     rounds = 0
  69.     took_step = True
  70.     look_direction = deque(['N', 'S', 'W', 'E'])
  71.     duplicates = set()
  72.     while took_step:
  73.         elves_set = set(elves)
  74.         next_step = [None] * len(elves)
  75.         took_step = False
  76.         rounds += 1
  77.         duplicates.clear()
  78.         for i, elf in enumerate(elves):
  79.             for n in nearby(elf):
  80.                 if n in elves_set:
  81.                     took_step = True
  82.                     for look in look_direction:
  83.                         for nn in look_around(elf, look):
  84.                             if nn in elves_set:
  85.                                 break
  86.                         else:
  87.                             next_step[i] = elf + CARD_DIR[look]
  88.                             break
  89.                     break
  90.         counts = Counter(next_step)
  91.         for i, elf in enumerate(next_step):
  92.             if counts[elf] == 1:
  93.                 elves[i] = elf
  94.  
  95.         if not part2 and rounds == 10:
  96.             break
  97.  
  98.         look_direction.rotate(-1)
  99.         # print_scan(elves)
  100.     if not part2:
  101.         elf_real = [int(elf.real) for elf in elves]
  102.         elf_imag = [int(elf.imag) for elf in elves]
  103.  
  104.         val = (max(elf_real) - min(elf_real) + 1) * (max(elf_imag) - min(elf_imag) + 1) - len(elves)
  105.     else:
  106.         val = rounds
  107.     # print_scan(elves)
  108.     return val
  109.  
  110.  
  111. def main():
  112.     assert day23('test23') == 110
  113.     print(f"Part 1: {day23('input23')}")
  114.  
  115.     assert day23('test23', True) == 20
  116.     print(f"Part 2: {day23('input23', True)}")
  117.  
  118.  
  119. if __name__ == '__main__':
  120.     main()
  121.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement