Chapter 119
Bananas to the Bazaar
You have bananas and a camel that carries at most at a time. The bazaar is miles away. Whenever the camel is carrying bananas it eats one per mile travelled; when it carries none it walks free. What is the largest number of bananas you can get to the bazaar, and how?
The Riddler, FiveThirtyEight(original post)
Solution
The detail that unlocks everything is the free walk back. The camel eats only when loaded, so an empty return trip costs nothing, and the only thing you ever pay for is a loaded mile. Three thousand bananas do not fit in one load, so to inch the whole hoard forward by a mile you must drive the camel forward loaded three times, eating three bananas for that mile. The plan, then, is to shed loaded trips as fast as you can.
A hoard of bananas needs loaded passes to advance, so the cost per mile is while you hold more than bananas, drops to once you are at or below , and drops to once you are at or below . Cross each threshold as early as possible.
Stage 1. Start with bananas, paying per mile. Walk until the hoard falls to : that costs bananas, so it happens after Stage 2. Now bananas, paying per mile. Walk until the hoard falls to : another bananas, after You are now miles along, holding exactly bananas, with miles left.
Stage 3. A single load, paying per mile, over the final miles. You arrive with bananas, so you can sell . Crossing the thresholds any later would drag the expensive multi-pass miles out longer, and you cannot cross them earlier, so this is the best you can do.
The computation
Encode the rule, not the answer. Track the hoard as it moves: at each moment the number of loaded passes is , and that many bananas vanish per mile. To confirm the staging is optimal rather than assumed, sweep the distance at which you first consolidate the hoard and check that the best outcome is the one above.
import math
def deliver(B, cap=1000, dist=1000):
pos, bananas = 0.0, float(B)
while pos < dist - 1e-12:
passes = math.ceil(round(bananas, 9) / cap) # loaded forward trips
if passes <= 1:
bananas -= (dist - pos); break
drop = bananas - (passes - 1) * cap # shed one pass after this
seg = min(drop / passes, dist - pos)
bananas -= passes * seg; pos += seg
return bananas
print("delivered :", round(deliver(3000), 4))
def first_station(d1): # 3 passes for d1 miles, then play on
b = 3000 - 3 * d1
if d1 < 0 or d1 > 1000 or b < 0:
return -1
return deliver(b, 1000, 1000 - d1)
best = max((round(first_station(i / 4), 4), i / 4) for i in range(4001))
print("best, where:", best)
# delivered : 833.3333
# best, where: (833.3333, 333.25)