This one looks slightly annoying to parse, but not exactly the worst. The actual problem doesn't seem that bad though: First, find every possible solution to get to a given prize's X position given the X values, then see if the Y values would also reach there. There can only be so many valid values for just X, and only so many of those for Y, right?
Or maybe I can just brute force it?
private int GetLeastTokensBrute(Machine machine)
{
int least = int.MaxValue;
for (int a = 0; a <= 100; a++)
{
for (int b = 0; b <= 100; b++)
{
if ((machine.ax * a) + (machine.bx * b) == machine.targetX &&
(machine.ay * a) + (machine.by * b) == machine.targetY)
{
var tokens = (a * 3) + b;
least = Math.Min(tokens, least);
}
}
}
return least;
}
I did try a more clever solution first, but it got a wrong answer on the input and I'm not sure why. This brute force solution somehow runs faster and gets the right answer.
Yep, I expected this kind of extreme change for the solution. Add a whole 10000000000000
to the goal range. Bleh. I do have to get clever anyway.
It's a linear equation kind of solver isn't it.
I admit, I'm not the best at linear equations, but admittedly this was simple enough that I was able to muddle through it. It would have been far easier if I could use some Matrix math, but I didn't want to go through the trouble of getting a library for it, or implementing matrix math myself, so I just kinda... hard-coded it for this solution I guess? That and some trial-and-error.
private long GetLeastTokensLinear(Machine m)
{
var bPress = (m.targetY * m.ax - m.targetX * m.ay) / (m.by * m.ax - m.bx * m.ay);
var aPress = (m.targetX - bPress * m.bx) / m.ax;
if (aPress > 0 &&
bPress > 0 &&
(aPress * m.ax + bPress * m.bx) == m.targetX &&
(aPress * m.ay + bPress * m.by) == m.targetY)
{
return (aPress * 3) + bPress;
}
return 0;
}
At least it runs fast.