Advertisement
Guest User

Untitled

a guest
Dec 22nd, 2022
244
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.08 KB | None | 0 0
  1. import itertools
  2. import random
  3. import time
  4.  
  5. X = [l for l in open('input.txt', 'r') if l.strip()]
  6.  
  7. _map = {}
  8. for i, l in enumerate(X):
  9.     instrs = []
  10.     if l[0] in ' .#':
  11.         for j, c in enumerate(l):
  12.             if c in '#.':
  13.                 _map[complex(j, i)] = c
  14.     else:
  15.         l = l.strip()
  16.         b = ''
  17.         for c in l + ' ':
  18.             if c.isdigit():
  19.                 b = b + c
  20.             else:
  21.                 if b:
  22.                     instrs.append(int(b))
  23.                     b = ''
  24.                 if c in 'LR':
  25.                     instrs.append(c)
  26.  
  27. W = int((len(_map) / 6) ** 0.5)
  28. facing_scores = {1 + 0j: 0, 0 - 1j: 1, -1 + 0j: 2, 0 + 1j: 3}
  29.  
  30. base = [None] * 6
  31. labels = {}
  32. label = 0
  33. by_label = [[] for _ in range(6)]
  34. while True:
  35.     try:
  36.         base[label] = p0 = min([p for p in _map if p not in labels], key=lambda p: (p.imag, p.real))
  37.     except:
  38.         break
  39.     for di in range(W):
  40.         for dj in range(W):
  41.             p = p0 + complex(di, dj)
  42.             labels[p] = label
  43.             by_label[label].append(p)
  44.     label += 1
  45.  
  46. pos_3d = {}
  47. def assign_faces(label, assigned_faces):
  48.     if label == 6:
  49.         return True
  50.     for f in itertools.product(range(3), range(2)):
  51.         if f in assigned_faces:
  52.             continue
  53.         assigned_faces.add(f)
  54.         for r in itertools.product(range(2), repeat=3):
  55.             added = []
  56.             good = True
  57.             for p in by_label[label]:
  58.                 z = p - base[label]
  59.                 z = (int(z.imag), int(z.real))
  60.                 if r[0]:
  61.                     z = z[::-1]
  62.                 if r[1]:
  63.                     z = (z[0], (W - 1) - z[1])
  64.                 if r[2]:
  65.                     z = ((W - 1) - z[0], z[1])
  66.                 z = z[:f[0]] + ((-1, W)[f[1]],) + z[f[0]:]
  67.                 pos_3d[p] = z
  68.                 added.append(p)
  69.                 for di, dj in itertools.product(range(-1, 2), repeat=2):
  70.                     if (di == 0) == (dj == 0):
  71.                         continue
  72.                     q = p + complex(di, dj)
  73.                     if q in pos_3d:
  74.                         if int(sum(abs(a - b) for a, b in zip(pos_3d[p], pos_3d[q]))) != 1 + (labels[p] != labels[q]):
  75.                             good = False
  76.                             break
  77.                         else:
  78.                             pass
  79.                 if not good:
  80.                     break
  81.             if good and assign_faces(label + 1, assigned_faces):
  82.                 return True
  83.             for p in added:
  84.                 pos_3d.pop(p)
  85.         assigned_faces.remove(f)
  86.     return False
  87.  
  88. assigned_faces = set()
  89. assert assign_faces(0, assigned_faces)
  90. by_pos_3d = {}
  91. for p, z in pos_3d.items():
  92.     by_pos_3d[z] = p
  93.  
  94. for part2 in range(2):
  95.     j = base[0].real
  96.     facing = 1 + 0j
  97.     position = complex(j, 0)
  98.     for inst in instrs:
  99.         if type(inst) == int:
  100.             for _ in range(inst):
  101.                 p1 = position + facing
  102.                 f1 = None
  103.                 if p1 not in _map:
  104.                     if part2:
  105.                         z1 = pos_3d[position]
  106.                         z0 = pos_3d[position - facing]
  107.                         z2 = tuple(b + (b - a) for a, b in zip(z0, z1)) # step forwards
  108.                         z3 = tuple(b + {-1: 1, W: -1}.get(a, 0) for a, b in zip(z1, z2)) #project back onto the cube
  109.                         z4 = tuple(b + (b - a) for a, b in zip(z2, z3)) # move one step further along the new face
  110.                         p1 = by_pos_3d[z3]
  111.                         f1 = by_pos_3d[z4] - p1 # get the new facing direction
  112.                     else:
  113.                         p1 = position
  114.                         while p1 - facing in _map:
  115.                             p1 -= facing
  116.                 if _map[p1] == '#':
  117.                     break
  118.                 position = p1
  119.                 if f1 is not None:
  120.                     facing = f1
  121.         else:
  122.             facing *= {'R': 1j, 'L': -1j}[inst]
  123.  
  124.     position += 1 + 1j
  125.  
  126.     print(int(1000 * position.imag + 4 * position.real + facing_scores[facing]))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement