Chapter 93
What’s The Best Way To Drop A Smartphone?
You work for a tech firm developing a smartphone that supposedly survives falls from great heights, and you want to advertise the highest floor from which it can be dropped without breaking. You are given two phones and a 100-story tower. From any floor you may drop a phone; if it survives you may reuse it, but if it breaks it is gone. Using the two phones, what is the minimum number of drops that guarantees you can find the exact highest floor from which a phone does not break? What if the tower were 1,000 stories?
The Riddler, FiveThirtyEight(original post)
Solution
Plan the drops of the first phone in advance and ask how tall a tower a fixed budget of drops can resolve. Drop the first phone at some floor. If it breaks, the second phone is your only instrument, and it must walk up one floor at a time through the untested floors below, so with drops left it can clear at most of them. To stay within budget the first drop should therefore be at floor : a break there leaves floors through for the second phone, exactly more drops.
If instead the first phone survives floor , one drop is spent and remain, so the next first-phone drop may sit floors higher, at . Each survival lets the next gap shrink by one. The highest floor reachable in drops is thus The smallest that covers floors is the smallest with . For , since , the answer is . For , since , the answer is .
The computation
Encode the choice itself. Let be the largest number of floors that phones and drops can fully resolve. One drop splits the tower: if the phone breaks, phones and drops resolve the floors below; if it survives, phones and drops resolve the floors above; the tested floor is pinned. So . The answer is the least with .
from functools import lru_cache
@lru_cache(maxsize=None)
def resolvable(phones, drops): # most floors p phones, d drops can resolve
if phones == 0 or drops == 0:
return 0
return resolvable(phones - 1, drops - 1) + resolvable(phones, drops - 1) + 1
def min_drops(phones, floors):
d = 0
while resolvable(phones, d) < floors:
d += 1
return d
print(min_drops(2, 100), min_drops(2, 1000))
# 14 45