Advertisement
strigido

Day 8 part 1 visualization code

Dec 31st, 2024
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.42 KB | Software | 0 0
  1. import numpy as np
  2. from PIL import Image, ImageDraw
  3.  
  4.  
  5. # Read the input file
  6. with open('input.txt', 'r') as file:
  7.     antenna_grid = np.array([[x for x in line] for line in file.read().split('\n') if line != ''])
  8. rows, cols = antenna_grid.shape
  9.  
  10. # Extract antenna positions from the grid
  11. antenna_positions = {}
  12. for r, c in zip(*np.nonzero(antenna_grid != '.')):
  13.     frequency = antenna_grid[r, c]
  14.     if frequency not in antenna_positions:
  15.         antenna_positions[frequency] = [(r, c)]
  16.     else:
  17.         antenna_positions[frequency].append((r, c))
  18.  
  19.  
  20. class Antinode:
  21.     def __init__(self, pos: tuple[int, int]):
  22.         self.pos = pos
  23.         self.diameter = 100
  24.         self.animating = True
  25.    
  26.     def update(self):
  27.         if self.diameter > 30:
  28.             self.diameter -= 2.5
  29.         else:
  30.             self.animating = False
  31.    
  32.     def draw(self, draw: ImageDraw):
  33.         draw.circle(self.pos, self.diameter/2, outline='#f00', width=int(-1/7*self.diameter + 21))
  34.  
  35.  
  36. W = 2300
  37. H = 2500
  38. GRID_SIZE = 2200
  39. GRID_X = (W - GRID_SIZE) / 2
  40. GRID_Y = (W - GRID_SIZE) / 2 + H - W
  41.  
  42. def grid_to_image_coords(x: int, y: int) -> tuple[int, int]:
  43.     return (x + 1) * (GRID_SIZE / (cols+1)), (y + 1) * (GRID_SIZE / (cols+1))
  44.  
  45. frame = 0
  46. def draw_frame():
  47.     # DRAW GRID IMAGE
  48.    
  49.     grid_img = Image.new(mode='RGB', size=(GRID_SIZE, GRID_SIZE), color='#fff')
  50.     draw = ImageDraw.Draw(grid_img)
  51.    
  52.     # antinodes
  53.     for antinode in antinodes:
  54.         antinode.draw(draw)
  55.    
  56.     # line
  57.     if line_pos1 != None != line_pos2:
  58.         draw.line((line_pos1, line_pos2), fill='#88f', width=20, joint='curve')
  59.         draw.circle(pos1, 45, fill='#00f')
  60.         draw.circle(pos2, 40, fill='#00f')
  61.    
  62.     # antennas
  63.     for frequency in antenna_positions:
  64.         for r, c in antenna_positions[frequency]:
  65.             pos = grid_to_image_coords(r, c)
  66.             fill = '#000' if pos1 == None or pos1 != pos != pos2 or line_pos1 == None else '#fff'
  67.             size_mult = 1.0 if pos1 == None or pos1 != pos != pos2 or line_pos1 == None else 1.5
  68.             draw.text(pos, frequency, fill=fill, font_size=(GRID_SIZE / (cols-1)) * size_mult, anchor='mm')
  69.    
  70.     img = Image.new(mode='RGB', size=(W, H), color='#fff')
  71.     draw = ImageDraw.Draw(img)
  72.    
  73.     # DRAW COMPLETE FRAME
  74.    
  75.     img = Image.new(mode='RGB', size=(W, H), color='#fff')
  76.     draw = ImageDraw.Draw(img)
  77.    
  78.     # paste image
  79.     p = 8
  80.     draw.rectangle((GRID_X - p, GRID_Y - p, GRID_X + GRID_SIZE + p, GRID_Y + GRID_SIZE + p), fill='#333')
  81.     Image.Image.paste(img, grid_img, (int(GRID_X), int(GRID_Y)))
  82.    
  83.     # counter
  84.     draw.text((W / 2, 140), f'antinode locations: {len(antinode_positions)}', fill='#000', font_size=135, anchor='mm')
  85.    
  86.     global frame
  87.     img.save(f'./frames/frame_{str(frame).zfill(4)}.png', 'PNG')
  88.     frame += 1
  89.  
  90.  
  91. # Check each pair of antennas for antinodes
  92. antinodes = []
  93. def update_all_antinodes():
  94.     for antinode in antinodes:
  95.         antinode.update()
  96. antinode_positions = set()
  97. line_pos1 = line_pos2 = pos1 = pos2 = None
  98. draw_frame()
  99. for frequency in antenna_positions:
  100.     for i, (r1, c1) in enumerate(antenna_positions[frequency]):
  101.         for j, (r2, c2) in enumerate(antenna_positions[frequency][i+1:], 1):
  102.             antinode_r, antinode_c = r1 + r1-r2, c1 + c1-c2
  103.             line_pos1 = grid_to_image_coords(antinode_r, antinode_c)
  104.             if 0 <= antinode_r < rows and 0 <= antinode_c < cols:
  105.                 if (antinode_r, antinode_c) not in antinode_positions:
  106.                     antinodes.append(Antinode(grid_to_image_coords(antinode_r, antinode_c)))
  107.                     antinode_positions.add((antinode_r, antinode_c))
  108.             antinode_r, antinode_c = r2 + r2-r1, c2 + c2-c1
  109.             line_pos2 = grid_to_image_coords(antinode_r, antinode_c)
  110.             if 0 <= antinode_r < rows and 0 <= antinode_c < cols:
  111.                 if (antinode_r, antinode_c) not in antinode_positions:
  112.                     antinodes.append(Antinode(grid_to_image_coords(antinode_r, antinode_c)))
  113.                     antinode_positions.add((antinode_r, antinode_c))
  114.             pos1 = grid_to_image_coords(r1, c1)
  115.             pos2 = grid_to_image_coords(r2, c2)
  116.             for _ in range(4):
  117.                 draw_frame()
  118.                 update_all_antinodes()
  119.  
  120. line_pos1 = line_pos2 = None
  121. while any(antinode.animating for antinode in antinodes):
  122.     draw_frame()
  123.     update_all_antinodes()
  124.  
  125.  
  126.  
  127.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement