16

Two Egg problem:

  • You are given 2 eggs.
  • You have access to a 100-storey building.
  • Eggs can be very hard or very fragile means it may break if dropped from the first floor or may not even break if dropped from 100 th floor.Both eggs are identical.
  • You need to figure out the highest floor of a 100-storey building an egg can be dropped without breaking.
  • Now the question is how many drops you need to make. You are allowed to break 2 eggs in the process

I am sure the two egg problem ( mentioned above ) has been discussed sufficiently. However could someone help me understand why the following solution is not optimal.

Let's say I use a segment and scan algorithm with the segment size s. So,

d ( 100 / s   + (s-1) ) = 0    [ this should give the minima,  I need '(s-1)' scans per segment and there are '100/s' segments]
-
ds

=> -100 / s^2 + 1 = 0
=> s^2 = 100
=> s = 10

So according to this I need at most 19 drops. But the optimal solution can do this with 14 drops.

So where lies the problem?

Rohan Monga
  • 1,759
  • 1
  • 19
  • 31
  • 5
    This problem is also discussed here: http://stackoverflow.com/questions/6547/two-marbles/6871#6871 – Martin Nov 13 '10 at 10:14
  • yup, that's what I am unable to figure out, what are we missing in this differential that it is not giving the optima. – Rohan Monga Nov 13 '10 at 10:16
  • I'm unable to figure out what the problem is. Both eggs are identical but one will break at the first floor and the other won't even at 100? That ... is not identical by any definition of the term I'm familiar with. – JUST MY correct OPINION Nov 13 '10 at 10:48
  • @JUST both eggs are identical but you don't the floor where they would break. So, if one breaks on 87th floor, the other one will too. – Rohan Monga Nov 13 '10 at 10:52
  • Adding a link for some one new: [Q: 2 Eggs 100 Floors Puzzle](http://www.programmerinterview.com/index.php/puzzles/2-eggs-100-floors-puzzle/) – Grijesh Chauhan Sep 30 '13 at 06:46

10 Answers10

21

You seem to be assuming equal-sized segments. For an optimal solution, if the first segment is of size N, then the second has to be of size N-1, and so on (because when you start testing the second segment, you've already dropped the egg once for the first segment).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 2
    If you were to have three eggs. Would you simply drop the first egg from half way up the tower and then perform this 2 egg dropping problem on the appropriate half of the tower? Could there be a more optimal solution to this 3 egg dropping problem? – Ogen Sep 27 '14 at 05:23
  • 1
    I don't understand the part where you say : "then the second has to be of size N-1, and so on (because when you start testing the second segment, you've already dropped the egg once for the first segment).". Care to explain, why it's N-1 and not N ? – Dinaiz Jan 08 '17 at 15:09
  • why there should be a minimization of risk at each step with n-1, why not n-2, n-4 etc. – Prashant Sep 27 '18 at 15:06
  • I understand how this algorithm is faster compared to the OP's suggestion, but I fail to understand how this is the optimal solution. Is there any way to prove that this specific algorithm is the most efficient in terms of time-complexity? – Kcits970 Aug 18 '21 at 03:06
  • @kcits: Proof is left as an exercise for the reader. :-) – Jerry Coffin Aug 18 '21 at 04:27
8

So you need to solve n+(n-1)+(n-2)+...+1<=100, from where (n)(n+1)/2<=100 (this function transform is done with arithmetic series aka sum of an arithmetic sequence), now if you solve for n (wolframalpha: Reduce[Floor[n + n^2] >= 200, n] ) you get 14. Now you know that the first floor where you need to make the drop is 14th floor, next will be (14+14-1)th floor and whole sequence:

14; 27; 39; 50; 60; 69; 77; 84; 90; 95; 99; 100 

If you break the first egg, you go back to the last one and linearly check all options until you break the second egg, when you do, you got your answer. There is no magic.

http://mathworld.wolfram.com/ArithmeticSeries.html

Margus
  • 19,694
  • 14
  • 55
  • 103
6

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)
Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219
  • Your solution is no better. It still requires a minimum of 14 attempts to check all the floors. – q-l-p Jan 26 '23 at 19:48
2

A very nice explanation of the solution I found in the below link. The Two Egg Problem

It explains how you get to n+(n-1)+(n-2)+...+1<=100
The 1 Egg Problem - Linear Complexity O(100)
and Multiple(Infinite) Eggs Problem - Logarithmic complexity O(log2(100)).

DayaMoon
  • 357
  • 2
  • 7
  • But what is the complexity of the 2 egg problem? The infinite egg problem is a binary search, sure. The 1 egg problem is a linear search. The 2 egg problem is better than O(n) but worse than O(log n). Maybe O( x sqrt(n) ) or just O(sqrt(n) ) ? – Davos Aug 08 '17 at 14:25
2

I also had the same thought in mind . I was also trying to find the exact method you said . I cleared this solution as explained by one of the members here . But here is a bit more explanation if you might .

N is defined as the minimum no: of searches required .

I am trying to find a no: n such that it is the min no: of searches I have to make .

So I start at xth floor I have 2 scenarios ,

1) It breaks , I have to do x-1 more checking's (because I have only 1 more egg) . All's fair there . Total is 1+ x-1 = x searches .

Now we have defined this value as n . Hence x = n ! [PS : This might be trivial but this has some subtleties IMO]

2) It doesnt break - and I have used up one of my n possibilities already ! Now the searches allowed further is n - 1 . Only then the total no: of searches will be N and that is the definition of N . The problem now has become a sub problem of 100 - n floors with 2 eggs . If am chosing some yth floor now - its worst case should be n - 1 . (n - 1)th floor satisfies this .

Hence you get the pattern go to nth , n + (n -1 )th floor , n + (n - 1) + (n - 2)th floor .... Solve this for 100th floor and you get N . The floor you start with and the no: of searches is a coincidence I think .

To get the maxima n = 14 , you can think of having n bulbs with 2 bulbs glowing at once . It will require atleast 14 bulbs to cover all the possible combinations of where egg can break .

As a challenge try to do it for 3 eggs .

In your logic basically , there is an asymmetry in how the search progress . For the first set of 10 elements , the algorithm finds out quickly . I would suggest to try and check

http://ite.pubs.informs.org/Vol4No1/Sniedovich/ for some explnation and also try to visualize how this problem is seen in real cases of Networks .

Nishant
  • 20,354
  • 18
  • 69
  • 101
  • 1
    That link seems to be dead. https://pubsonline.informs.org/doi/pdf/10.1287/ited.4.1.48 works for me (The Joy of Egg-Dropping in Braunschweig and Hong Kong, Moshe Sniedovich) – peer Jan 03 '19 at 13:55
  • Thanks @peer, I will retain that link as well. – Nishant Jan 03 '19 at 14:04
1

Here's a solution in Python. If you drop the egg at a certain floor f, it either breaks or it doesn't, and in each case you have a certain number of floors you still need to check (which is a subproblem). It uses a recursion and also a lookup dictionary to make it much faster to compute.

neededDict = {}

# number of drops you need to make
def needed(eggs, floors):

    if (eggs, floors) in neededDict:
        return neededDict[(eggs, floors)]

    if eggs == 1:
        return floors

    if eggs > 1:

        minimum = floors
        for f in range(floors):
            #print f
            resultIfEggBreaks = needed(eggs - 1, f)
            resultIfEggSurvives = needed(eggs, floors - (f + 1))
            result = max(resultIfEggBreaks, resultIfEggSurvives)
            if result < minimum:
                minimum = result

        # 1 drop at best level f plus however many you need to handle all floors that remain unknown
        neededDict[(eggs, floors)] = 1 + minimum
        return 1 + minimum


print needed(2, 100)
Rick Giuly
  • 983
  • 1
  • 14
  • 19
  • This algorithm is inefficient and can't even handle needed(7, 16000) – SobiborTreblinka Jul 28 '14 at 23:51
  • Nice code! But I think those 2 lines `resultIfEggBreaks = needed(eggs - 1, f)` `resultIfEggSurvives = needed(eggs, floors - (f + 1))` need to be changed to `resultIfEggBreaks = needed(eggs - 1, f - 1)` `resultIfEggSurvives = needed(eggs, floors - f)` since in both cases you have to check one less floor. – insumity Jan 05 '16 at 00:24
1

The question should not be how many drops you need to make ? but rather than that it should be find the minimal number of drops in order to know where the egg breaks, I saw this issue on careercup, below is the algorithms I thought of:

There are two ways to solve this problem :

Once first egg is broken we know in which interval we need to look:

  1. binary example:

    we try 100/2 (50) if it broke we search from 1 to 50 incrementing by 1 if not we throw it from 50+100/2 (75) if it broke we search from 50 to 75 if not we throw it from 75+100/2 (87) if it broke we search from 75 to 87 incemrenting by one floor at a time and so on and so forth.

  2. fibonacy example: same thing : we try 1,2,3,5,8.13,... if first egg broke we get back to the last interval's minimum and increment by 1.

Community
  • 1
  • 1
Mehdi Karamosly
  • 5,388
  • 2
  • 32
  • 50
  • 1
    I think binary search is a good first thought, but you can't do a balanced binary search because the `egg breakage value` is a floor above which all eggs break, so the search space is not even. i.e. if the egg breaks at floor 50, you've only got one egg left. Worst case is 50, egg #1 breaks at 50 and then you scan from 1 to 49. Best case is it does or doesn't break at 100, 8 drops. The Fibonacci search is interesting too, thanks for link. Best case is it breaks on floor 1, 1 drop. Worst case it it breaks on floor 88, because the sequence doesn't end nicely near 100. 44 drops? – Davos Aug 08 '17 at 13:48
  • A true binary search is O(log n), but both of these are worse than that for this problem space, but what? probably something sub O(n) or equivalent. I wonder what. – Davos Aug 08 '17 at 13:50
0

hey what about this approach.

Try this sequence:

1,2,4,8,16,32,64,100

And once you find the egg is broken you well get a space to work on. lets suppose @ 64 egg breaks. then the answer lies between 32 & 64.

We can use normal binary search between those 2 number. we will check @ 48 (32+64)/2 and then we will get the upper half or lower half as shortlisted space. and repeat

In this case the worst case is having the floor at 99. which will take 14 tries.

  • 1
    In your example, lets say the floor where eggs break is 35. Using your method you will break both eggs, 1@64 and then 1@48, and all you will know is that the floor is somewhere between 33 and 48 and never get the real solution of 35. In this game you are only allowed to break both eggs if breaking both proves which floor is the maximum where an egg doesn't break. e.g. if you have dropped an egg at 99 and it doesn't break, and then it breaks at 100, you can definitively say that 99 is the highest floor where the egg doesn't break. – Davos Aug 08 '17 at 12:59
0

The explanation of the two eggs problem can make some people confused in the first time, so we can understand the solution as follows: Given x is the floor we start dropping the eggs: - If it breaks, the total of trials in the worst case is x + (x - 1) - If it doesn't break, how should we step up to the next floor? We can jump to floor (x + x)th, (x + x + 1)th... But it will increase the number of trials, we can try at x = 10: . If it does break, we must try 10 times total in the worst case. . If it does not break, and we step up to 10th + 10th = 20th and try, and if it breaks, we must try 1 (at floor 10th) + 1 (at floor 20th) + 9 = 11 times. Similarly, if we step up to x + 1, or x + 2 floor it will increase the number of trials. Actually, we want the number of trials being equal in both cases, for that reason we will step up to x - 1 floor instead of x, x + 1.,etc. Finally, we will have an expression in general: x + (x - 1) + (x - 2) + ... + 1. And that's it.

-1

I would say the optimal solution for 100 floors with two eggs is 13 tries not 14.
13, 25, 36, 46, 55, 64, 72, 79, 85, 90, 94, 97, 99, 100 is the optimal answer, but if I reach to 99 I do not really need to try out 100. It is obvious the correct answer without try to drop egg from 100th floor :D