cant_stop
% cant_stop.pi (in Picat)
% by N.F. Zhou, Dec. 26, 2015
% https://code.google.com/codejam/contest/2437491/dashboard#s=p3
% World Finals 2013
% Problem D. Can't Stop
% based on the analysis:
% https://code.google.com/codejam/contest/2437491/dashboard#s=a&a=3
% to use: picat cant_stop < input_file > output_file
%
main =>
T = to_int(read_line()),
foreach(TC in 1..T)
not not do_case(TC)
end.
do_case(TC) =>
N = read_int(), D = read_int(), K = read_int(),
Sets = new_array(N),
foreach (I in 1..N)
Sets[I] = [read_int() : _ in 1..D]
end,
awesome(K, Sets, 1, N, Y, Z, _Len),
printf("Case #%w: %w %w\n", TC, Y-1, Z-1).
awesome(K, Sets, Lo, Hi, Y, Z, Len), Lo > Hi => Len = 0.
awesome(K, Sets, Lo, Hi, Y, Z, Len), Lo+1 >= Hi => Len = Hi-Lo+1, Y = Lo, Z = Hi. % since K >= 2
awesome(K, Sets, Lo, Hi, Y, Z, Len) =>
Mi is (Lo+Hi) div 2,
maxof_awesome_cross(K, Sets, Lo, Hi, Mi, YMi, ZMi, LenMi),
awesome(K, Sets, Lo, Mi-1, YLo, ZLo, LenLo),
awesome(K, Sets, Mi+1, Hi, YHi, ZHi, LenHi),
(LenLo >= LenMi, LenLo >= LenHi ->
Len = LenLo, Y = YLo, Z = ZLo
;LenMi >= LenLo, LenMi >= LenHi ->
Len = LenMi, Y = YMi, Z = ZMi
;
Len = LenHi, Y = YHi, Z = ZHi
).
% the same as maxof(awesome_cross(K, Sets, Lo, Hi, Mi, Y, Z, Len), Len) but more efficient
%
maxof_awesome_cross(K, Sets, Lo, Hi, Mi, Y, Z, Len) ?=>
M = get_global_map(),
M.put(Mi,{0,0,0}),
awesome_cross(K, Sets, Lo, Hi, Mi, Y, Z, Len),
{Len0,Y0,_} = M.get(Mi),
(Len > Len0 ->
M.put(Mi, {Len,Y,Z})
; Len == Len0,Y < Y0 ->
M.put(Mi, {Len,Y,Z})
;
true
),
fail.
maxof_awesome_cross(K, Sets, Lo, Hi, Mi, Y, Z, Len) =>
M = get_global_map(),
M.get(Mi) = {Len,Y,Z}.
awesome_cross(K, Sets, Lo, Hi, Mi, Y, Z, Len) =>
member(E, Sets[Mi]),
ASet = [E],
expand(K, Sets, Lo, Hi, Mi-1, Mi+1, Y, Z, ASet),
Len = Z-Y+1.
expand(K, Sets, Lo, Hi, Left, Right, Y, Z, ASet),
Lo <= Left,
member(E,ASet),
member(E,Sets[Left])
=>
expand(K, Sets, Lo, Hi, Left-1, Right, Y, Z, ASet).
expand(K, Sets, Lo, Hi, Left, Right, Y, Z, ASet),
Right <= Hi,
member(E,ASet),
member(E,Sets[Right])
=>
expand(K, Sets, Lo, Hi, Left, Right+1, Y, Z, ASet).
expand(K, Sets, Lo, Hi, Left, Right, Y, Z, ASet),
Lo <= Left,
len(ASet) < K
?=>
member(E,Sets[Left]),
expand(K, Sets, Lo, Hi, Left-1, Right, Y, Z, [E|ASet]).
expand(K, Sets, Lo, Hi, Left, Right, Y, Z, ASet),
Right <= Hi,
len(ASet) < K
=>
member(E,Sets[Right]),
expand(K, Sets, Lo, Hi, Left, Right+1, Y, Z, [E|ASet]).
expand(K, Sets, Lo, Hi, Left, Right, Y, Z, _ASet) =>
Y = Left+1,
Z = Right-1.