Академический Документы
Профессиональный Документы
Культура Документы
Description
A recent interesting problem in computer science involves determining which floor in a high rise building an egg
will break if dropped. The problem states that only two eggs are allowed for the test and that there is a lowest floor
at which the egg will break if dropped. The egg will break for all floors above this floor, but will not break for all
floors below. The solution is to find the lowest floor at which the egg breaks using the least number of attempts.
1. Analysis of Problem
On first site, an optimal algorithm that uses the least number of attempts would appear to be some variation of a
binary search method. With this approach, the first egg would be dropped from the middle floor of the building, and
if it does not break then the egg would be dropped on the floor half-way from the middle to the top (or at about ¾ of
the way up). If it still does not break than we keep halving the distance to the top until it does break, at which point
we would need to use the second egg and make attempts one floor at a time from the last floor that the first egg did
not break to the last one where it did break. The first floor at which the second egg does break would then be the
lowest floor. This approach is pseudo-coded below in Figure 1.0:
function binarySearch(floor[])
bottom := 1
top := floor.number
while bottom < top
middle := lower_bound((top-bottom)/2)+top
if floor[middle] = EGG_BREAKS
for i from bottom to middle
if floor[i] = EGG_BREAKS
return i
else
bottom := middle+1
return not found
Figure 1.0
In the worst case scenario, however, if the lowest floor at which the egg breaks is the 50 th floor of a 100 story
building, this variation on a binary search would take 50 attempts.
A better heuristic would be to use a stepped incremental search approach. With this approach, starting from a given
small incremented number of floors from the first floor, we drop the first egg. If the egg breaks, then using the
second egg we only have a small incremented number of floors to test from the first floor, one floor at a time, to
determine the lowest floor where the egg breaks. If the egg does not break, then we continually go up the same
incremented number of floors until the first egg does break. At this point, we use the second egg to test from the
previously tested floor that is at most an incremented number of floors below the current floor, again one floor at a
time, to determine the lowest floor where the egg breaks. This approach is pseudo-coded below in Figure 2.0:
1
function stepSearch(floor[], increment)
test := increment
top := floor.number
while test < top
if floor[test] = EGG_BREAKS
for i from test-(increment-1) to test
if floor[i] = EGG_BREAKS
return i
else
test := test+increment
if test > top
test = top
return not found
Figure 2.0
As an example, using a stepped increment of 10 floors in a 100 story building, the worst case scenario would occur
if the lowest floor at which the egg breaks is from the 99th floor. In this case, we would search the 10th, 20th, 30th, up
to the 100th floor followed by the 91st, 92nd, 93rd, up to the 99th floor at which point a total of 19 attempts would have
been made. Hence, the stepped incremental search shows a significant improvement of taking only 19 attempts over
the varied binary search, which would take 50 attempts in a worst case scenario.
To determine the minimum value of the function, we use the Calculus First Derivative Test that first involves taking
the derivative of the function 𝛉 with respect to 𝒊 as follows:
𝛛 𝒏
𝛉(𝒊) = 𝟏 − (2)
𝛛𝒊 𝒊𝟐
The critical points of 𝛉 are determined when the derivative of this function is zero. From (2),
𝒏
𝟎 = 𝟏− (3)
𝒊𝟐
𝒊𝟐 = 𝒏 (4)
𝒊 = ±√𝒏 (5)
Since the number of floors 𝒏 and the increment 𝒊 must be positive and can typically be considered to be greater than
one for all practical purposes, it follows that
2
Based on (6) and the derivative of the function 𝜽 in (2):
𝛛
𝜽(𝟏) = 𝟏 − n < 𝟎 (7)
𝛛𝒊
𝛛 𝟏
𝜽(𝒏) = 𝟏 − > 𝟎 (8)
𝛛𝒊 𝒏
Thus, from the First Derivative Test, it follows from (7) that the function 𝜽 is decreasing on the interval [𝟏, √𝐧) and
from (8) that the function 𝜽 is increasing on the interval (√𝒏, ∞) so that for the stepped increment search the
minimum number of attempts will occur when the increment is given by the square root of the number of floors
specified for the problem:
𝒊 = √𝒏 (9)
If (9) is taken as the value of the increment in the stepped increment search, it follows that the number of attempts in
the worst case scenario for the two egg problem is given by the following based on (1) and (9):
𝒏
𝛉(𝒏) = + √𝒏 − 𝟏 (10)
√𝒏
In terms of order in Big “O” notation, the order for the stepped increment search using (9) for the increment then
becomes:
𝜣(√𝒏)
This order has significantly higher performance in comparison to the initially proposed variation of a binary search
to solve the two egg problem. In fact, the variation of binary search has a worst case scenario of 𝒏/𝟐 , and
consequently has an order 𝒏, which has significantly lower performance than the stepped increment search:
𝜣(𝒏)
Figure 3.0 illustrates graphs for various orders (including the orders √𝒏 and 𝒏 for the different algorithms discussed
here) that map the size of the data set 𝒏 against the number of operations 𝑵 performed. This corresponds to the
number of floors against the number of attempts required to solve the two egg problem. The significant difference
between how the graphs of the orders √𝒏 and 𝒏 increase with the data set size clearly shows the difference in
potential performance between the two different algorithms considered to solve the two egg problem.
3
Figure 3.0
4
Two Egg Problem for 100 Floors
14.00000
12.00000
10.00000
Avergae Attempts
8.00000
6.00000
4.00000
2.00000
0.00000
0 2 4 6 8 10 12 14 16
Step Increment Size
Figure 4.0
14.90000
14.80000
14.70000
14.60000
14.50000
14.40000
14.30000
14.20000
0 5 10 15 20 25
Step Increment Size
Figure 5.0
5
Two Egg Problem for 300 Floors
18.80000
18.60000
18.40000
Average Attempts
18.20000
18.00000
17.80000
17.60000
17.40000
0 5 10 15 20 25
Step Increment Size
Figure 6.0
21.00000
Average Attempts
20.80000
20.60000
20.40000
20.20000
20.00000
0 5 10 15 20 25 30
Step Increment Size
Figure 7.0
6
Two Egg Problem for 500 Floors
23.10000
23.00000
22.90000
Average Attempts
22.80000
22.70000
22.60000
22.50000
22.40000
0 5 10 15 20 25 30
Step Increment Size
Figure 8.0
7
Appendix I
////////////////////////////////////////////////////////////////////////////////////////////////////
// Test to Determine the Optimal Solution to the Two Egg Problem //
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Standard C Header Files
//
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <math.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
// Testing Structure and Function //
////////////////////////////////////////////////////////////////////////////////////////////////////
struct TestType
{
double TimeTaken;
unsigned long Operations;
unsigned long Solution;
bool Successful;
};
struct TestType StepSearch(bool Floor[], unsigned long FloorCount, unsigned long Increment)
{
TestType StepSearchTest;
bool TestSuccessful;
bool TestCompleted;
LARGE_INTEGER ClockTicksPerSecond;
LARGE_INTEGER ClockTicksStart;
LARGE_INTEGER ClockTicksEnd;
QueryPerformanceFrequency(&ClockTicksPerSecond);
QueryPerformanceCounter (&ClockTicksStart);
TestSuccessful = false;
TestCompleted = false;
Test = Increment - 1;
Top = FloorCount - 1;
OperationCount = 0;
//
// Ihe main part of the algorithm starts at this point. It loops until conditions inside
// the loop causes the test completed value to be set to true.
//
while(TestCompleted == false)
{
OperationCount++;
//
// If the egg breaks from the current floor then go down to one floor above the
// previously tested floor, where the egg did not break. This floor would be a whole
// number of floors (going down) based on the increment value plus one. From this
// floor, go up one floor at a time until the second egg breaks, which is the solution
// to the problem.
//
if (Floor[Test] == true)
{
Test = Test - (Increment - 1);
8
//
// Go up a whole incremented number of floors from the current floor otherwise, unless
// the incremented number of floors will exceed the total number of floors. In this
// case go to the top floor.
//
else
{
if (Test + Increment < Top)
{
Test += Increment;
}
else
{
Test = Top;
}
}
}
QueryPerformanceCounter(&ClockTicksEnd);
StepSearchTest.Operations = OperationCount;
StepSearchTest.Solution = Test;
StepSearchTest.Successful = TestSuccessful;
StepSearchTest.TimeTaken = (ClockTicksEnd.QuadPart - ClockTicksStart.QuadPart) * 1000.0 /
(ClockTicksPerSecond.QuadPart);
return StepSearchTest;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Constants for Testing //
////////////////////////////////////////////////////////////////////////////////////////////////////
const int NumberOfTests = 5;
const int MaximumFloors = 500;
const int NumberOfFloors[ ] = { 100, 200, 300, 400, 500 };
const int IncrementStart[ ] = { 5, 10, 12, 15, 18 };
const int IncrementEnd [ ] = { 15, 20, 22, 25, 28 };
////////////////////////////////////////////////////////////////////////////////////////////////////
// Main Function for the Test //
////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
TestType StepSearchTest;
bool Floor[MaximumFloors];
int TestNumber = 0;
int TestOperations = 0;
double TestTimeTaken = 0;
printf("\n");
printf("--------------------------------------------------------- \n");
printf(" Testing Solutions to the Two Egg Problem \n");
printf("--------------------------------------------------------- \n");
printf("---- ------ --------- ------------------ ------------ \n");
printf("Test Floors Increment Average Operations Average Time \n");
printf("---- ------ --------- ------------------ ------------ \n");
9
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// End of File //
////////////////////////////////////////////////////////////////////////////////////////////////////
10
Appendix II
---------------------------------------------------------
Testing Solutions to the Two Egg Problem
---------------------------------------------------------
---- ------ --------- ------------------ ------------
Test Floors Increment Average Operations Average Time
---- ------ --------- ------------------ ------------
0001 100 5 12.700 0.000057 s
0002 100 6 11.540 0.000041 s
0003 100 7 10.840 0.000067 s
0004 100 8 10.460 0.000221 s
0005 100 9 10.210 0.000031 s
0006 100 10 10.100 0.000036 s
0007 100 11 10.190 0.000046 s
0008 100 12 10.420 0.000072 s
0009 100 13 10.610 0.000046 s
0010 100 14 10.770 0.000036 s
0011 100 15 11.160 0.000036 s
11