Advertisement
alexandrajay2002

Advent of Code 2024 day 21

Dec 21st, 2024
302
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.04 KB | Source Code | 0 0
  1. from functools import cache
  2. from argparse import ArgumentParser, FileType
  3.  
  4.  
  5. def parse(src):
  6.     return [line for line in src.splitlines() if line != '']
  7.  
  8.  
  9. def distance(start, end):
  10.     return end[0] - start[0], end[1] - start[1]
  11.  
  12.  
  13. numeric_coord = {
  14.     'A': (2, 3),
  15.     '0': (1, 3),
  16.     '1': (0, 2),
  17.     '2': (1, 2),
  18.     '3': (2, 2),
  19.     '4': (0, 1),
  20.     '5': (1, 1),
  21.     '6': (2, 1),
  22.     '7': (0, 0),
  23.     '8': (1, 0),
  24.     '9': (2, 0)
  25. }
  26.  
  27. coord_numeric = {
  28.     (2, 3): 'A',
  29.     (1, 3): '0',
  30.     (0, 2): '1',
  31.     (1, 2): '2',
  32.     (2, 2): '3',
  33.     (0, 1): '4',
  34.     (1, 1): '5',
  35.     (2, 1): '6',
  36.     (0, 0): '7',
  37.     (1, 0): '8',
  38.     (2, 0): '9'
  39. }
  40.  
  41.  
  42. direction_coord = {
  43.     'A': (2, 0),
  44.     '^': (1, 0),
  45.     '>': (2, 1),
  46.     'v': (1, 1),
  47.     '<': (0, 1)
  48. }
  49.  
  50. coord_direction = {
  51.     (2, 0): 'A',
  52.     (1, 0): '^',
  53.     (2, 1): '>',
  54.     (1, 1): 'v',
  55.     (0, 1): '<'
  56. }
  57.  
  58.  
  59. @cache
  60. def move(button, next_button, numeric):
  61.     if button == next_button:
  62.         return 'A'
  63.  
  64.     if numeric:
  65.         button_coord = numeric_coord
  66.         coord_button = coord_numeric
  67.     else:
  68.         button_coord = direction_coord
  69.         coord_button = coord_direction
  70.  
  71.     first_coord = button_coord[button]
  72.     next_coord = button_coord[next_button]
  73.     dx, dy = distance(first_coord, next_coord)
  74.  
  75.     if dx >= 0:
  76.         move_x = '>' * dx
  77.     else:
  78.         move_x = '<' * -dx
  79.  
  80.     if dy >= 0:
  81.         move_y = 'v' * dy
  82.     else:
  83.         move_y = '^' * -dy
  84.  
  85.     if dx == 0:
  86.         return move_y + 'A'
  87.     elif dy == 0:
  88.         return move_x + 'A'
  89.  
  90.     result = list()
  91.     # find the button with the x coord of next_button and the y coord of
  92.     # button, if it exists
  93.     if (next_coord[0], first_coord[1]) in coord_button:
  94.         result.append(move_x + move_y + 'A')
  95.  
  96.     # similar for y
  97.     if (first_coord[0], next_coord[1]) in coord_button:
  98.         result.append(move_y + move_x + 'A')
  99.  
  100.     # if we know one will be slower, remove it
  101.     if len(result) != 2 or dx < 0:
  102.         result = result[0]  # '<' is the slowest to get to 'A' from
  103.     else:
  104.         result = result[1]  # 'v' is slower than '^'
  105.  
  106.     return result
  107.  
  108.  
  109. @cache
  110. def get_sequence_length(sequence, indirection, numeric):
  111.     if indirection == 0:
  112.         return len(sequence)
  113.  
  114.     sequence = 'A' + sequence
  115.     total = 0
  116.     for button, next_button in zip(sequence, sequence[1:]):
  117.         total += get_sequence_length(move(button, next_button, numeric),
  118.                                      indirection - 1, False)
  119.     return total
  120.  
  121.  
  122. def type_code(code, indirection):
  123.     length = get_sequence_length(code, indirection + 1, True)
  124.     return length * int(code[:-1])
  125.  
  126.  
  127. def main(codes, indirection):
  128.     return sum(type_code(code, indirection) for code in codes)
  129.  
  130.  
  131. arg_parser = ArgumentParser()
  132. arg_parser.add_argument('src', type=FileType('r'))
  133. arg_parser.add_argument('indirection', nargs='?', type=int, default=2)
  134.  
  135. if __name__ == '__main__':
  136.     args = arg_parser.parse_args()
  137.     print(main(parse(args.src.read()), args.indirection))
  138.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement