Guest User

Untitled

a guest
Dec 21st, 2024
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.92 KB | None | 0 0
  1. # Input: three-digit numbers followed by "A"
  2. # Output: using 26 tiers of directional keypads
  3. #            ^A
  4. #           <v>
  5. #         (A = push button), get a numeric keypad
  6. #           789
  7. #           456
  8. #           123
  9. #            0A
  10. #         to type each line (while never pointing to a gap)
  11. #         find sum of (shortest sequence * three-digit number)
  12.  
  13. import itertools
  14.  
  15. from functools import cache
  16.  
  17. lines = []
  18.  
  19. file = open("21_input.txt", "r")
  20. for line in file:
  21.   line = line.replace("\n", "")
  22.   lines.append(line)
  23.  
  24. dk_keys = {} # key = character, value = [row, column]
  25. dk_keys[" "] = [0, 0]
  26. dk_keys["^"] = [0, 1]
  27. dk_keys["A"] = [0, 2]
  28. dk_keys["<"] = [1, 0]
  29. dk_keys["v"] = [1, 1]
  30. dk_keys[">"] = [1, 2]
  31.  
  32. nk_keys = {}
  33. nk_keys["7"] = [0, 0]
  34. nk_keys["8"] = [0, 1]
  35. nk_keys["9"] = [0, 2]
  36. nk_keys["4"] = [1, 0]
  37. nk_keys["5"] = [1, 1]
  38. nk_keys["6"] = [1, 2]
  39. nk_keys["1"] = [2, 0]
  40. nk_keys["2"] = [2, 1]
  41. nk_keys["3"] = [2, 2]
  42. nk_keys[" "] = [3, 0]
  43. nk_keys["0"] = [3, 1]
  44. nk_keys["A"] = [3, 2]
  45.  
  46. # assumption: longer sequence of presses never has lower cost
  47.  
  48. def get_sequences(dict):
  49.   derived_dict = {}
  50.   for current in dict:
  51.     if current == " ":
  52.       continue
  53.     for goal in dict:
  54.       if goal == " ":
  55.         continue
  56.       cr, cc = dict[current][0], dict[current][1]
  57.       gr, gc = dict[goal][0], dict[goal][1]
  58.       keys_up_down = ""
  59.       keys_left_right = ""
  60.       for r in range(abs(cr - gr)):
  61.         if cr > gr:
  62.           keys_up_down += "^"
  63.         if cr < gr:
  64.           keys_up_down += "v"
  65.       for c in range(abs(cc - gc)):
  66.         if cc > gc:
  67.           keys_left_right += "<"
  68.         if cc < gc:
  69.           keys_left_right += ">"
  70.       key_lists = []
  71.       key_lists.append(keys_up_down + keys_left_right)
  72.       key_lists.append(keys_left_right + keys_up_down)
  73.       options = []
  74.       for key_list in list(set(key_lists)):
  75.         # if it crosses a gap, then omit it
  76.         r, c = cr, cc
  77.         key_list_valid = True
  78.         for key in key_list:
  79.           if key == "^":
  80.             r -= 1
  81.           if key == "v":
  82.             r += 1
  83.           if key == "<":
  84.             c -= 1
  85.           if key == ">":
  86.             c += 1
  87.           if r == dict[" "][0] and c == dict[" "][1]:
  88.             key_list_valid = False
  89.             break
  90.         if key_list_valid:
  91.           options.append(key_list)
  92.       derived_dict[current + goal] = options
  93.   return derived_dict
  94.  
  95. d2d = get_sequences(dk_keys)
  96. n2d = get_sequences(nk_keys)
  97.  
  98. @cache
  99. def get_all_sub_sequences(str, use_n2d):
  100.   dict = d2d
  101.   if use_n2d:
  102.     dict = n2d
  103.   if len(str) == 1:
  104.     return [""]
  105.   options = []
  106.   for next_step in dict[str[:2]]:
  107.     for rest_of_steps in get_all_sub_sequences(str[1:], use_n2d):
  108.       options.append(next_step + "A" + rest_of_steps)
  109.   return list(set(options))
  110.  
  111. @cache
  112. def get_all_sequences(str, use_n2d):
  113.   return get_all_sub_sequences("A" + str, use_n2d)
  114.  
  115. d2d_tiered = {}
  116. number_tiers = 25
  117.  
  118. def get_tier_key(pair, tier):
  119.   return pair + "," + str(tier)
  120.  
  121. for tier in range(number_tiers, 0, -1):
  122.   for pair in d2d:
  123.     s_list = get_all_sub_sequences(pair, False)
  124.     shortest_cost = -1
  125.     for s in s_list:
  126.       cost = 0
  127.       if tier == number_tiers:
  128.         cost = len(s)
  129.       else:
  130.         s2 = "A" + s
  131.         for i in range(len(s2) - 1):
  132.           cost += d2d_tiered[get_tier_key(s2[i:i+2], tier + 1)]
  133.       if shortest_cost == -1 or shortest_cost > cost:
  134.         shortest_cost = cost
  135.     d2d_tiered[get_tier_key(pair, tier)] = shortest_cost
  136.  
  137. total = 0
  138. for line in lines:
  139.   code = int(line.replace("A", ""))
  140.   options = get_all_sequences(line, True)
  141.   shortest_cost = -1
  142.   for option in options:
  143.     cost = 0
  144.     option2 = "A" + option
  145.     for i in range(len(option2) - 1):
  146.       cost += d2d_tiered[get_tier_key(option2[i:i+2], 1)]
  147.     if shortest_cost == -1 or shortest_cost > cost:
  148.       shortest_cost = cost
  149.   total += code * shortest_cost
  150. print (total)
Add Comment
Please, Sign In to add comment