Day 13: Claw Contraption
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Python
I just threw linear algebra and float64 on this question and it stuck. Initially in order to decrease the numbers a bit (to save precision) I tried to find greatest common divisors for the coordinates of the target but in many cases it was 1, so that was that went down the drain. Luckily float64 was able to achieve precisions up to 1e-4 and that was enough to separate wheat from chaff. So in the end I did not have to use exact formulas for the inverse of the matrix though probably would be a more satisfying solution if I did.
import numpy as np
from functools import partial
from pathlib import Path
cwd = Path(__file__).parent
def parse_input(file_path, correction):
with file_path.open("r") as fp:
instructions = fp.readlines()
machine_instructions = []
for ind in range(0,len(instructions)+1,4):
mins = instructions[ind:ind+3]
machine_instructions.append([])
for i,s in zip(range(3),['+','+','=']):
machine_instructions[-1].append([int(mins[i].split(',')[0].split(s)[-1]),
int(mins[i].split(',')[1].split(s)[-1])])
for i in range(2):
machine_instructions[-1][-1][i] += correction
return machine_instructions
def solve(threshold, maxn, vectors):
c = np.array([3, 1])
M = np.concat([np.array(vectors[0])[:,None],
np.array(vectors[1])[:,None]],axis=1).astype(int)
if np.linalg.det(M)==0:
return np.nan
Minv = np.linalg.inv(M)
nmoves = Minv @ np.array(vectors[2])
if np.any(np.abs(nmoves - np.round(nmoves))>threshold) or\
np.any(nmoves>maxn) or np.any(nmoves<0):
return np.nan
return np.sum(c * (Minv @ np.array(vectors[2])))
def solve_problem(file_name, correction, maxn, threshold=1e-4):
# correction 0 or 10000000000000
# maxn 100 or np.inf
machine_instructions = parse_input(Path(cwd, file_name), correction)
_solve = partial(solve, threshold, maxn)
tokens = list(map(_solve, machine_instructions))
return int(np.nansum(list(tokens)))