egg_drop
``` ```
% egg_drop.pi (in Picat)
% by N.F. Zhou, Jan. 24, 2016
% Practice Problems
% Problem C. Egg Drop
%
% to use: picat egg_drop < input_file > output_file
%

main =>
foreach (TC in 1..T)
do_case(TC, F, D, B)
end.

do_case(TC, F, D, B) =>
MF = max_f(D, B),
min_d(F, MD, B),
min_b(F, D, MB),
printf("Case #%w: %w %w %w\n", TC, MF, MD, MB).

% maximize F for given D and B
max_f(D, B) = F, D >= 100000, B >= 2 =>  F = -1.
max_f(D, B) = F, D >= 10000, B >= 3 =>  F = -1.
max_f(D, B) = F, D >= 1000, B >= 4 =>  F = -1.
max_f(D, B) = F, B > D => F = max_f(D, D).
max_f(D, B) = f(D, B).

table
f(_, 0) =  0.
f(D, 1) =  D.
f(0, _) =  0.
f(1, _) =  1.
f(D, B) =  F =>
F1 = f(D-1,B),
F2 = f(D-1,B-1),
if F1 == -1 ; F2 == -1 then
F = -1
else
F0 = F1+F2+1,
F = cond(F0 >= 2**32, -1, F0)
end.

% minimize D for given F and B
min_d(F, D, B) =>
bsearch_d(0, F, F, D, B).

bsearch_d(From, To, F, D, B), From >= To =>
D = cond((max_f(From, B) >= F ; max_f(From, B) == -1), From, From+1).
bsearch_d(From, To, F, D, B) =>
Mid = (From+To) div 2,
if max_f(Mid, B) == F then
D = Mid
elseif max_f(Mid, B) == -1 ; max_f(Mid, B) > F then
bsearch_d(From, Mid-1, F, D, B)
else
bsearch_d(Mid+1, To, F, D, B)
end.

% minimize B for given F and D
min_b(F, D, B) =>
bsearch_b(0, F, F, D, B).

bsearch_b(From, To, F, D, B), From >= To =>
B = cond((max_f(D, From) >= F ; max_f(D, From) == -1), From, From+1).
bsearch_b(From, To, F, D, B) =>
Mid = (From+To) div 2,
if max_f(D, Mid) == F then
B = Mid
elseif max_f(D, Mid) == -1 ; max_f(D, Mid) > F then
bsearch_b(From, Mid-1, F, D, B)
else
bsearch_b(Mid+1, To, F, D, B)
end.
``````