I've been trying to work through a math problem and wanted to see if it's feasible to solve within a certain number of moves.
A target point is placed at unknown coordinates (tx, ty) where both tx and ty are uniformly random in [-20,000,000, 20,000,000]. You start at the origin (0, 0).
Each turn, you move by a delta (dx, dy) of your choice. Your move must be at least 20 ft (sqrt(dx² + dy²) ≥ 20). After each move, you receive the change in your Euclidean distance to the target compared to your previous position, rounded deterministically to the nearest 5 ft.
Formally: feedback_delta = round_to_nearest_5(dist(new_pos, target) - dist(old_pos, target)). Positive means you got further, negative means closer.
Your goal is to move within 1 ft of the target in the fewest moves possible.
With my current approach I can make it in 70 or so moves, but it feels like there should be a more precise solution that takes fewer.
My solution so far:
1. Find the approximate angle
Move +100,000 ft on the x-axis, record the delta as a, then -100,000 ft on the x-axis to return to (0, 0). Do the same for the y-axis and record that delta as b. The approximate direction to the target is then the unit vector (a, b) / ||(a, b)||. The rounding introduces some uncertainty here though, which compounds over long distances.
2. Move toward that direction as far as possible
Since both coordinates are bounded by [-20,000,000, 20,000,000], the max distance you can travel along direction (a, b) is limited by whichever axis hits a wall first:
d_max = min(20,000,000 / |a|, 20,000,000 / |b|) · ||(a, b)||
The x and y components of the move are then:
dx = d_max · a / ||(a, b)||
dy = d_max · b / ||(a, b)||
Record the delta as c. This intentionally overshoots the target.
3. Backtrack based on delta
You moved M ft total (where M is d_max from previous step) and recorded delta c. The distance to the target before the move was:
D = (M - c) / 2
where c is signed (negative = closer, positive = further). The overshoot is M - D:
overshoot = (M + c) / 2
So to backtrack:
dx = -overshoot · a / ||(a, b)||
dy = -overshoot · b / ||(a, b)||
This gets within a few thousand ft, but lateral error from the imprecise angle in step 1 adds significant uncertainty.
4. Search for rounding boundaries for a more precise angle
To get a more precise angle than step 1 we find the exact move distance in both x and y where the rounded feedback flips between two values.
From the coarse angle I believe we can compute the minimum range guaranteed to contain a rounding boundary. A 1 ft change in move distance changes the true delta by approximately cos(α) on the x-axis and sin(α) on the y-axis. To guarantee crossing a 5 ft rounding boundary:
x_range = 5 / cos(α)
y_range = 5 / sin(α)
So for x: move +1,000 ft, record the delta, move back. Then move +(1,000 + x_range) ft, record the delta, move back. These two should be guaranteed to produce different rounded values. Now binary search between them: try the midpoint, see which way it rounds, halve the interval, repeat until the range between the two bracketing distances is less than 0.1 ft.
At that boundary, the true delta equals exactly the midpoint between the two rounded values (e.g., if 1,002.2 gives 980 and 1,002.3 gives 985, the true delta is 982.5 at move distance ≈1,002.25). This gives cos(α) = 982.5 / 1,002.25 with much higher precision.
Repeat for y. Then the refined direction vector is (cos(α), sin(α)). The cost is several turns per axis though.
5. Rinse and repeat: overshoot, backtrack, and refine the angle
We can repeat steps 2–4, getting closer to the target with each cycle. I believe if it's done correctly we should be able to get within 1 ft within a couple of cycles, but I'm not fully confident about that.
An alternative solution I considered, but haven't played with: instead of angle-based triangulation, binary search each axis independently. Move to the midpoint of the x-range, probe to determine which side the target is on, halve the range, repeat. This would probably still need some cycles though so I'm not sure if this is the best approach.
I've created a small codepen for the problem that I've been using to test strategies.
So I'm wondering: is there a more efficient strategy, and is there a way to determine the maximum number of turns a strategy would take?
My initial thoughts are that with better math we could potentially avoid returning to an origin point when probing, but I'm not sure how. It also seems like there should be a way to determine the exact precision of the angle needed to avoid multiple refinement cycles.
Also, does the 20 ft minimum displacement per turn add significant difficulty, or is the problem essentially the same without it?
I also don't have a background in math and don't fully understand all of the formulas I've been using but they are what I found when trying to find formulas that represented how my brain thought about each step.