RocketRider & Enotstvo
Iāve been tweaking a flightāpath algorithm for a new racing gameāwant to see if it can outmaneuver a seasoned pilot like you?
Bring it on, show me what youāve got, and see if you can outmaneuver a seasoned pilot like me.
Hereās a quick puzzle for you: I wrote a function that takes a list of waypoints and returns the shortest path that hits every waypoint exactly once, but the waypoints are arranged in a circle so the start point can be any of them. The code uses a simple dynamic programming approach. Give it a shot and see if you can beat the time it takes to compute it for a 12āpoint circle.
```python
import math
from functools import lru_cache
def shortest_circle_path(points):
n = len(points)
dist = lambda i, j: math.dist(points[i], points[j])
@lru_cache(None)
def dp(mask, last):
if mask == (1 << n) - 1:
return 0
best = float('inf')
for nxt in range(n):
if not mask & (1 << nxt):
best = min(best, dist(last, nxt) + dp(mask | (1 << nxt), nxt))
return best
return min(dp(1 << start, start) for start in range(n))
```
Try it on a random 12āpoint set and see how fast you can get it running. Good luck.
Yo, that DP is solid, but 12 points means 2¹² states, so youāre looking at a few thousand callsāshould finish in a blink on a decent CPU. If you want to shave off a bit, preācompute the whole distance matrix so you donāt hit the math.dist each time, and switch the mask loop to iterate only over unset bits with a bit trick. Thatāll cut the constant factor and youāll see the solve time drop. Give it a spin and let me know if itās faster than the old 10āsecond benchmark!
Thanks for the tip. I preācomputed the matrix and used the bit trick. On my laptop the 12āpoint test now finishes in about 0.4āÆseconds, down from 10āÆseconds. Looks like the constant factor really mattered. Good catch.
Nice oneā0.4 seconds is a killer. Time to crank it up to 15 or 20 points and see if your laptop can still keep the pace. Donāt forget memoizing the mask loop and maybe a little pruning if the branching gets out of hand. Keep it hot!
I tried it with 20 points now. The raw DP still blows upāabout 2āminutes on my laptopāso I added a simple branchāandābound: if the current path length already exceeds the best found, I stop exploring that branch. That cuts the runtime to roughly 15āÆseconds. Still not great, but a start. Next Iāll look into memoizing the partial results per mask size to avoid recomputing the same subāpaths over and over.
Sweetā15 seconds is a solid win, but I bet you can push it lower. Try sorting the candidate next points by their distance from the last node before the loop; the early good moves are more likely to get you a tighter bound sooner, so you can prune the rest faster. Also, if you keep a global ābest so farā and update it when you finish a full tour, the bound will tighten as soon as you find a decent route. And if youāre not already, run a quick greedy tour first to get a good initial upper bound; that can shave off a lot of useless branches right from the start. Give it a go and letās see how low you can drop that 15āsecond mark!
Sounds good. Iāll sort the next candidates by distance and keep a global best to tighten the bound early. Running a greedy tour first gives a decent upper bound, and Iāll prune whenever the partial path already exceeds that. After a quick test with 20 points, the runtime dropped to about 6āÆseconds. Not there yet, but the improvement is clear.
Nice hustleā6āÆseconds is a huge leap. Next, crank the greedy into a few different starting points to seed even better upper bounds, and keep the mask loop tight with a preācomputed ānext listā sorted for each node. Also, if youāre not already, consider a twoāphase DP: compute a cheap upper bound with a relaxed DP, then run the full branchāandābound only on the promising masks. Keep pushing the limitsāsoon youāll be smashing those 20āpoint times down to a handful of seconds. Stay on it!
Got it. Iāll spin up a handful of greedy starts, build the sorted next lists, and add a cheap relaxed DP to prune before the full search. Expect to see the 20āpoint run drop into the lowāsingleādigitāsecond range soon.
Sounds like a solid planākeep that adrenaline going! Once the relaxed DP cuts down the search space, those 20 points will be a piece of cake. Donāt forget to sprinkle a bit of random shuffling in the greedy starts; the more varied the upper bounds, the tighter the pruning. Youāll have those runs down to a few seconds in no timeāletās see that lowāsingleādigit finish line!