/*
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
*/
/*
* Memoized Egg Dropper
* By Alex Ponebshek
*
* This is a program to solve the Google egg-dropping puzzle, generalized to more than 2 eggs.
* It uses memoization for efficiency.
* I still think it could be made more efficient by using a binary search to find the optimal drop floor.
*
* It can print the full decision tree for egg dropping.
*/
public class EggDropper
{
public static void main
(String[] args
)
{
System.
out.
println("Dropping eggs...");
int eggs=3;
int stories=100;
EggDropper e=new EggDropper(eggs, stories); // Pepare the computat0r!
System.
out.
println("It will take "+e.
eggdrop(eggs, stories
)+" drops."); // Print worst case drops
e.eggdrop_treewalk(eggs, stories, 0, 0, false); // Print decision tree
}
//f(1,b)=b, f(a,b)=1+max(f(a-1,x), f(a, b-x-1)) where x is whatever value of x would make f(a,b) the lowest
private int[][] droppages;
public EggDropper(int maxeggs, int maxlevels)
{
droppages=new int[maxeggs-1][maxlevels-1];
}
public int eggdrop(int a, int b)
{
if (b==0) // No ambiguity, so no testing required
return 0;
if (b==1) // One last drop! I'm such an idiot for missing this before.
return 1;
if (a<=1) // One egg, so exhaustive search
return b;
if (droppages[a-2][b-2] == 0) // If it's not in the table...
droppages[a-2][b-2]=eggdrop_calc(a, b); // calculate it!
return droppages[a-2][b-2];
}
private int eggdrop_calc(int a, int b)
{
for (int i=2; i<b; i++) // Precompute for lower floors to shake the obscenely deep recursion out ;)
eggdrop(a, i);
int follow=beatdrop(a, b, 0);
for (int x=1; x<b; x++) // Loop to find optimal floor from which to drop this floor
{
follow
=Math.
min(follow, beatdrop
(a, b, x
));
}
return follow+1;
}
private int beatdrop(int a, int b, int x) // Find worst case of smash or no smash for a given drop
{
return Math.
max(eggdrop
(a
-1, x
), eggdrop
(a, b
-x
-1
));
}
/**
* Outputs a decision tree
* Each line is spaced out by the number of drops that already happened.
* A number means "drop from this floor".
* The next line is what happens if there was no smash,
* and the following line at that tablevel is what happens if there is a smash.
*
* n : Drop on floor n
* =n: Smashpoint is n
* ~n: Smashpoint is either n or n+1; drop at n
* ~n,m: Smashpoint is from n to m+1; dropscan from n to m
*/
public void eggdrop_treewalk(int a, int b, int prefixed, int rebase, boolean smashfun)
{
tabOut(prefixed);
// Note to me: a is at least 1, and b is... fuck b.
if (b<=0) // Not sure if this can happen, but I'm afraid to remove it >_>
{
System.
out.
println("="+rebase
);
return;
}
if (b==1)
{
System.
out.
println("~"+rebase
);
return;
}
if (a<=1)
{
System.
out.
println("~"+rebase
+","+(rebase
+b
-1
));
return;
}
eggdrop(a, b); // Makes sure the table is filled out
int follow=beatdrop(a, b, 0);
int opx=0; // now we track optimal floor
for (int x=1; x<b; x++)
{
int drop=beatdrop(a, b, x);
if (drop<follow || (smashfun && drop==follow))
{
follow=drop;
opx=x;
}
}
System.
out.
println(opx
+rebase
);
eggdrop_treewalk(a , b-opx-1, prefixed+1, rebase+opx+1, smashfun); // If it doesn't break
eggdrop_treewalk(a-1, opx , prefixed+1, rebase , smashfun); // If it does break
}
private void tabOut(int spaces)
{
for (;spaces
>0;spaces
--) System.
out.
print(" ");
}
}
/*
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFJGpK3wwWAXIUwsAcRAv7KAJ47XjIYK4/iObsmuiWTZOxnMtujYwCeIe2U
3F/U5THbCw4z+DWueKd84e4=
=MUj1
-----END PGP SIGNATURE-----
*/