Advertisement
Guest User

AOC 2021 Day 13

a guest
Dec 20th, 2021
708
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.17 KB | None | 0 0
  1. # aoc202113.py
  2.  
  3. import numpy as np
  4. import pathlib
  5. import re
  6. import sys
  7. from typing import TypeVar
  8.  
  9. C = TypeVar("list[tuple[int, int]]")
  10.  
  11.  
  12. def parse(puzzle_input: str) -> tuple[C, C]:
  13.     """ Parse input """
  14.     dots, instructions = puzzle_input.split('\n\n')
  15.     # Process coordinates
  16.     coords = []
  17.     for dot in dots.split('\n'):
  18.         x, y = [int(d) for d in dot.split(',')]
  19.         coords.append((x, y))
  20.     # Process instructions
  21.     folds = []
  22.     pattern = re.compile(r"fold along (x|y)=(\d+)")
  23.     for fold in instructions.split('\n'):
  24.         match = re.search(pattern, fold)
  25.         direction, value = match.groups()
  26.         if direction == 'x':
  27.             folds.append((int(value), 0))
  28.         elif direction == 'y':
  29.             folds.append((0, int(value)))
  30.     return (coords, folds)
  31.  
  32.  
  33. def make_grid(coords: C) -> 'np.ndarray[int]':
  34.     """ Work out dimensions of inital gird, retun as zeroed array """
  35.     exes, whys = [], []
  36.     for (x, y) in coords:
  37.         exes.append(x)
  38.         whys.append(y)
  39.     return np.zeros((max(whys) + 1, max(exes) + 1), dtype=int)
  40.  
  41.  
  42. def update_grid(coords: C, grid: 'np.ndarray[int]') -> None:
  43.     """ Change grid coords to 1 based on input """
  44.     for (x, y) in coords:
  45.         grid[y][x] = 1
  46.  
  47.  
  48. def split_grid(
  49.         grid: 'np.ndarray[int]',
  50.         fold: tuple[int, int]) -> tuple['np.ndarray[int]', 'np.ndarray[int]']:
  51.     """ Return a grid split either x or y axis """
  52.     x, y = fold
  53.     if x == 0:
  54.         return (grid[:y], grid[y + 1:][::-1])
  55.     elif y == 0:
  56.         return (grid[:, :x], np.flip(grid[:, x + 1:], 1))
  57.  
  58.  
  59. def part1(data: tuple[C, C]) -> int:
  60.     """ Solve part 1 """
  61.     coords, folds = data
  62.     page = make_grid(coords)
  63.     # Add coords to grid
  64.     update_grid(coords, page)
  65.     first_half, second_half = split_grid(page, folds[0])
  66.     combined = np.where(second_half == 1, second_half, first_half)
  67.     return np.count_nonzero(combined == 1)
  68.  
  69.  
  70. def printable(num: int) -> str:
  71.     """ Return a string dependent on value of num """
  72.     return "#" if num == 1 else " "
  73.  
  74.  
  75. def print_grid(grid: 'np.ndarray[int]') -> None:
  76.     """ Print grid """
  77.     for row in grid:
  78.         print("".join(printable(val) for val in row))
  79.  
  80.  
  81. def part2(data: tuple[C, C]) -> str:
  82.     """ Solve part 2 """
  83.     coords, folds = data
  84.     page = make_grid(coords)
  85.     # Add coords to grid
  86.     update_grid(coords, page)
  87.     for fold in folds:
  88.         first, second = split_grid(page, fold)
  89.         page = np.where(second == 1, second, first)
  90.     print_grid(page)
  91.     answer = input("Write down the code above: ")
  92.     return answer
  93.  
  94.  
  95. def solve(puzzle_input: str) -> tuple[int, str]:
  96.     """ Solve the puzzle for the given input """
  97.     data = parse(puzzle_input)
  98.     solution1 = part1(data)  # Correct answer was 682 (with my data)
  99.     solution2 = part2(data)  # Correct answer was "FAGURZHE" (with my data)
  100.  
  101.     return solution1, solution2
  102.  
  103.  
  104. if __name__ == "__main__":
  105.     for path in sys.argv[1:]:
  106.         print(f"{path}:")
  107.         puzzle_input = pathlib.Path(path).read_text().strip()
  108.         solutions = solve(puzzle_input)
  109.         print('\n'.join(str(solution) for solution in solutions))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement