Correct and optimal solution is 13, 25, 36, 46, 55, 64, 72, 79, 85, 90, 94, 97, 99, 100
in which average number of trials of finding floor on which egg breaks is minimum, assuming floor on which egg breaks is selected randomly.
Based on this information we can write a recursive function to minimize average trials, that gives a solution of
13, 25, 36, 46, 55, 64, 72, 79, 85, 90, 94, 97, 99, 100
It has following max trials for each floor-step
13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14
This is obviously much better than naive solution arrived by assuming gaps starting at 14 and reducing. In this case 55% of time you just need 13 trials. It is very near to optimal solution derived from n (n+1) / 2 >= 100
which gives n = 13.651
and our optimal solution is (13*5+14*9)/14
i.e. 13.643
Here is a quick implementation:
import sys
def get_max_trials(floors):
pf = 0
trials = []
for i, f in enumerate(floors):
trials.append(i+f-pf)
pf = f
return trials
def get_trials_per_floor(floors):
# return list of trials if egg is assumed at each floor
pf = 0
trials = []
for i, f in enumerate(floors):
for mid_f in range(pf+1,f+1):
trial = (i+1) + f - mid_f + 1
if mid_f == pf+1:
trial -= 1
trials.append(trial)
pf = f
return trials
def get_average(floors):
trials = get_trials_per_floor(floors)
score = sum(trials)
return score*1.0/floors[-1], max(trials)
floors_map = {}
def get_floors(N, level=0):
if N == 1:
return [1]
if N in floors_map:
return floors_map[N]
best_floors = None
best_score = None
for i in range(1,N):
base_floors = [f+i for f in get_floors(N-i, level+1)]
for floors in [base_floors, [i] + base_floors]:
score = get_average(floors)
if best_score is None or score < best_score:
best_score = score
best_floors = floors
if N not in floors_map:
floors_map[N] = best_floors
return best_floors
floors = get_floors(100)
print "Solution:",floors
print "max trials",get_max_trials(floors)
print "avg.",get_average(floors)
naive_floors = [14, 27, 39, 50, 60, 69, 77, 84, 90, 95, 99, 100]
print "naive_solution",naive_floors
print "max trials",get_max_trials(naive_floors)
print "avg.",get_average(naive_floors)
Output:
Solution: [13, 25, 36, 46, 55, 64, 72, 79, 85, 90, 94, 97, 99, 100]
max trials [13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14]
avg. (10.31, 14)
naive_solution [14, 27, 39, 50, 60, 69, 77, 84, 90, 95, 99, 100]
max trials [14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12]
avg. (10.35, 14)