2011 LP Programming Contest


chicken.pi

 
main => test.

test => chicken(5).

chicken(N) =>
    NR is 5+2*(N-1),
    NC is 7*2*(N-1)+6,
    A = new_array(NR,NC),
    place_u(A,2*(N-1)+1,1,N),
    (N mod 2=:=0->place_c2(A,1,7*(N-1)+1); place_c1(A,1,7*(N-1)+1)),
    place_d(A,3,7*(N-1)+7,N),
    foreach(R in 1..NR) 
        foreach(C in 1..NC)
            (var(A[R,C])->print(" "); printf("%c",A[R,C]))
        end,
	nl
    end.	    

place_u(_A,_R,_C,I), I=<1 => true.
place_u(A,R,C,I) =>
    place_cb(A,R,C),
    place_u(A,R-2,C+7,I-1).

place_d(_A,_R,_C,I), I=<1 => true.
place_d(A,R,C,I) =>
    place_bc(A,R,C),
    place_d(A,R+2,C+7,I-1).
    
place_c1(A,R,C) =>
    place_s(A,R,C,  "   \\\\ "),
    place_s(A,R+1,C,"   (o>"),
    place_s(A,R+2,C,"\\\\_//)"),
    place_s(A,R+3,C," \\_/_)"),
    place_s(A,R+4,C,"___|__").

place_c2(A,R,C) =>
    place_s(A,R,C,  "   // "),
    place_s(A,R+1,C,"   <o)"),
    place_s(A,R+2,C,"(\\\\_//"),
    place_s(A,R+3,C,"(_\\_/)"),
    place_s(A,R+4,C,"__|___").

place_cb(A,R,C) =>
    place_s(A,R,C,  "   \\\\  "),
    place_s(A,R+1,C,"   (o> "),
    place_s(A,R+2,C,"\\\\_//) "),
    place_s(A,R+3,C," \\_/_)|"),
    place_s(A,R+4,C,"___|__|").

place_bc(A,R,C) =>
    place_s(A,R,C,  "  //   "),
    place_s(A,R+1,C," <o)  "),
    place_s(A,R+2,C," (\\\\_//"),
    place_s(A,R+3,C,"|(_\\_/ "),
    place_s(A,R+4,C,"|__|___").

place_s(_A,_R,_C,[]) => true.
place_s(A,R,C,[X|Xs]) =>
    A[R,C] = X,
    place_s(A,R,C+1,Xs).

pattern.pi

 
import cp.

main => test.

test => pattern(3,L), writeln(L).

pattern(N,L) =>
    M is 2**N,
    LBs = new_list(M),
    foreach(Bs in LBs)
        Bs = new_list(N), 
        Bs :: 0..1
    end,
    Bs0 = [0 : _ in 1..N],
    LBs=[Bs0|LBs1],
    last(LBs) = Bs1,
    constr([Bs1|LBs]),
    solve(LBs),
    N1 is N-1,
    Dum = new_list(N1),
    once(append(LBs2,Dum,LBs1)),
    flat(LBs2,L1),
    Bs0++L1 = L.
    
constr([_]) => true.
constr([Bs1,Bs2|LBs]) =>
    [_|Sub] = Bs1,
    once(append(Sub,[_],Bs2)),
    foreach(Bs in LBs) diff(Bs,Bs2) end,
    constr([Bs2|LBs]).

diff(Bs1,Bs2) =>
    Disj = 0,
    foreach({B1,B2} in zip(Bs1,Bs2))
        Disj := Disj #\/ (B1 #!= B2)
    end,
    call(Disj).

flat([],L) => L=[].
flat([Bs|LBs],L) =>
    L = [B|L1],
    last(Bs) = B,
    flat(LBs,L1).

war.pi

 
main => test.

test =>
    war($[joint(m,5,5,5),joint(p,10,5,5),joint(s,5,1,1)],
	$[street(m,s),street(p,s)],
	N),
    writeln(N).

war(Js,Ss,NW) =>
    Js.length = N,
    Ws = [W : $joint(X,_,_,_) in Js, nw(X,Js,Ss,N,W)],
    sort(Ws) = [NW|_].

nw(X,Js,Ss,N,W) =>
    nw(X,Js,Ss,[],N,W).

table (+,+,+,+,+,min)
nw(X,Js,_Ss,_Path,1,W) =>
    (member($joint(X,Ne,In,De),Js)->true;true),
    W is max(In+De,Ne).
nw(X,Js,Ss,Path,C,W) =>
    (    member($street(X,Y),Ss)
     ;
         member($street(Y,X),Ss)
    ),
    not  member(Y,Path), 
    C1 is C-1,
    nw(Y,Js,Ss,[X|Path],C1,W1),
    (member($joint(X,Ne,In,De),Js)->true;true),
    W is max(W1+In+De,Ne).

race.pi

 
main => test.

test => race($[1-1,1-2],4,4,Winner), writeln(Winner).

race(Ps,N,M,W) =>
    L = [(Len,P) : P in Ps, path(P,1,1,N,M,Len)],
    sort(L) = SL,
    SL=[(_,W)|_].

table (+,+,+,+,+,min)
path(_,N,M,N,M,Len) => Len=0.
path(P,I,J,N,M,Len) =>
    next(P,I,J,I1,J1,N,M),
    path(P,I1,J1,N,M,Len1),
    Len is Len1+1.

next(D1-D2,I,J,I1,J1,N,M) ?=>
  I1 is I+D1, J1 is J+D2,
  I1>=1, I1=<N,
  J1>=1, J1=<M.
next(D1-D2,I,J,I1,J1,N,M) ?=>
  I1 is I-D1, J1 is J+D2,
  I1>=1, I1=<N,
  J1>=1, J1=<M.
next(D1-D2,I,J,I1,J1,N,M) ?=>
  I1 is I+D1, J1 is J-D2,
  I1>=1, I1=<N,
  J1>=1, J1=<M.
next(D1-D2,I,J,I1,J1,N,M) ?=>
  I1 is I-D1, J1 is J-D2,
  I1>=1, I1=<N,
  J1>=1, J1=<M.
%
next(D1-D2,I,J,I1,J1,N,M) ?=>
  I1 is I+D2, J1 is J+D1,
  I1>=1, I1=<N,
  J1>=1, J1=<M.
next(D1-D2,I,J,I1,J1,N,M) ?=>
  I1 is I-D2, J1 is J+D1,
  I1>=1, I1=<N,
  J1>=1, J1=<M.
next(D1-D2,I,J,I1,J1,N,M) ?=>
  I1 is I+D2, J1 is J-D1,
  I1>=1, I1=<N,
  J1>=1, J1=<M.
next(D1-D2,I,J,I1,J1,N,M) =>
  I1 is I-D2, J1 is J-D1,
  I1>=1, I1=<N,
  J1>=1, J1=<M.

plumber.pi

 
main => test.

test =>
   Grid = [[_,_],[$pipe(yes,yes,no,no),_]],
   Pieces = $[pipe(yes,no,no,yes),pipe(no,yes,yes,no),pipe(no,no,yes,yes)],
   plumber(Grid, Pieces),
   writeln(Grid).
/*
   Grid = [[pipe(no,yes,yes,no),pipe(no,no,yes,yes)],
           [pipe(yes,yes,no,no),pipe(yes,no,no,yes)]].
*/

plumber(Grid, Ps) =>
    Grid.length = N,
    TagPs = [(P,_) : P in Ps],
    foreach(I in 1..N, J in 1..N) place(Grid,I,J,N,TagPs) end.

place(Grid,I,J,N,Ps) =>
    place_piece(Grid,I,J,Ps,P),
    (I==1->no_up(P); I==N->no_down(P); true),
    (J==1->no_left(P); J==N->no_right(P); true),
    I1 is I+1,
    (I1=<N ->
	 place_piece(Grid,I1,J,Ps,Pd),    
	 match(P,Pd,down)
     ;
         true
    ),
    J1 is J+1,
    (J1=<N ->
	 place_piece(Grid,I,J1,Ps,Pr),    
	 match(P,Pr,right)
     ;
         true
    ).

place_piece(Grid,I,J,Ps,P) =>
    P = Grid[I,J],
    (var(P) -> member((P,Tag),Ps),var(Tag),Tag=1; true).

match(pipe(X,_,_,_),pipe(_,_,X,_),down) => true.
match(pipe(_,_,_,X),pipe(_,X,_,_),right) => true.

no_up(pipe(no,_,_,_)) => true.

no_right(pipe(_,no,_,_)) => true.

no_down(pipe(_,_,no,_)) => true.

no_left(pipe(_,_,_,no)) => true.