Guest User

Advent Day 24 Part 2

a guest
Dec 25th, 2023
382
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.29 KB | Software | 0 0
  1. import re
  2. import sys
  3. import numpy as np
  4.  
  5. def advent_day24_part2(filestr):
  6.     field = [x for x in filestr.split('\n') if x]
  7.     nrows, ncols = len(field), len(field[0])
  8.  
  9.     stones = []
  10.     for line in field:
  11.         m = re.split(r'[, @]+', line)
  12.         if m:
  13.             vals = [int(x) for x in m]
  14.             p = tuple(vals[:3])
  15.             v = tuple(vals[3:])
  16.             stones.append((p, v))
  17.  
  18.     # x = [sx sy sz wx wy wz t1 t2 ... tn]
  19.     # x_n+1 = x_n - J(x_n)^-1 f(x_n)
  20.     # f(x) = sx + wx * t1 - (px1 + vx1 * t1)
  21.     #      = (sx - px1) + (wx - vx1) * t1
  22.     # ... and again for y and z
  23.     # ... and again for all n
  24.     # J_x = [ 1  0  0 t1  0  0  wx-vx1  0  0 ...]
  25.     # J_y = [ 0  1  0  0 t1  0  wy-vy1  0  0 ...]
  26.     # J_z = [ 0  0  1  0  0 t1  wz-vz1  0  0 ...]
  27.  
  28.     ps = np.array(tuple(row[0] for row in stones), dtype=np.float64)
  29.     vs = np.array(tuple(row[1] for row in stones), dtype=np.float64)
  30.     x = np.array([0, 0, 0, 1, 1, 1] + [0] * nrows, dtype=np.float64)
  31.  
  32.     def jacobian(x, vs):
  33.         data = np.zeros((nrows * 3, 6 + nrows))
  34.         for i in range(nrows):
  35.             for j in range(3):
  36.                 r = 3 * i + j
  37.                 data[r, j] = 1
  38.                 data[r, 3 + j] = x[6 + i]
  39.                 data[r, 6 + i] = x[3 + j] - vs[i][j]
  40.         return data
  41.  
  42.     def func(x, ps, vs):
  43.         data = np.zeros(nrows * 3)
  44.         for i in range(nrows):
  45.             for j in range(3):
  46.                 r = 3 * i + j
  47.                 t = x[6 + i]
  48.                 sp = x[j] + x[3 + j] * t
  49.                 hp = ps[i][j] + vs[i][j] * t
  50.                 data[r] = sp - hp
  51.         return data
  52.  
  53.     sum0 = 0
  54.     for i in range(100):
  55.         print(i, np.sum(x[:3]), np.int64(x[0:3]), x[3:6])
  56.         j = jacobian(x, vs)
  57.         f = func(x, ps, vs)
  58.         dx, resid, rank, sing = np.linalg.lstsq(j, f, rcond=None)
  59.         x -= dx
  60.         sum1 = np.sum(x[:3])
  61.         if abs(sum1 - sum0) < 0.1:
  62.             break
  63.         sum0 = sum1
  64.     print(np.int64(x[:3]), np.int64(x[3:6]))
  65.     print(int(sum0))
  66.  
  67. def readfile(file_path):
  68.     with open(file_path, 'r') as file:
  69.         return file.read()
  70.  
  71. if __name__ == '__main__':
  72.     if len(sys.argv) >= 2:
  73.         filestr = readfile(sys.argv[1])
  74.     else:
  75.         filestr = ''
  76.     advent_day24_part2(filestr)
Add Comment
Please, Sign In to add comment