listlogic-programminganswer-set-programmingclingo

Riddle puzzle in clingo


So in the tag prolog someone wanted to solve the "the giant cat army riddle" by Dan Finkel (see video / Link for description of the puzzle).

Since I want to improve in answer set programming I hereby challenge you to solve the puzzle more efficient than me. You will find my solution as answer. I'll accept the fastest running answer (except if it's using dirty hacks).

Rules:


Solution

  • num(0..59).
    
    %valid operation pairs
    op(N*N,N):- N=2..7.  
    % no need to add operations that start with 14
    op(Ori,New):- num(Ori), New = Ori+7, num(New), Ori!=14.
    op(Ori,New):- num(Ori), New = Ori+5, num(New), Ori!=14.
    
    %iteratively create new numbers from old numbers
    l(0,0).
    {l(T+1,New) : op(Old,New)} = 1 :- l(T,Old), num(T+1), op(Old,_).
    
    %no number twice
    :- 2 #sum {1,T : l(T,Value)}, num(Value).
    
    %2 before 10 before 14
    %linear encoding
    reached(T,10) :- l(T,10).
    reached(T+1,10) :- reached(T,10), num(T+1).
    :- reached(T,10), l(T,2).
    
    :- l(T,14), l(T+1,_).
    
    %looks nicer, but quadratic
    %:- l(T2,2), l(T10,10), T10<T2.
    %:- l(T14,14), l(T10,10), T14<T10.
    
    %we must have these three numbers in the list somewhere
    :- not l(_,2).
    :- not l(_,10).
    :- not l(_,14).
    
    #show r(T,V) : l(T,V).
    #show.
    

    Having a slightly more ugly encoding improves grounding a lot (which was your main problem).

    1. I restricted op/2 to not start with 14, as this should be the last element in the list
    2. I do create the list iteratively, this may not be as nice, but at least for the start of the list it already removed impossible to reach values via grounding. So you will never have l(1,33) or l(2,45) etc... Also list generation stops when reaching the value 14, as no more operation is possible/needed.
    3. I also added a linear scaling version of the "before" section, although it is not really necessary for this short list (but a cool trick in general if you have long lists!) This is called "chaining".
    4. Also note that your show statement is non-trivial and does create some constraints/variables.

    I hope this helps, otherwise feel free to ask such questions also on our potassco mailing list ;)