Prolog Type Error

前端 未结 4 937
面向向阳花
面向向阳花 2021-01-27 07:23

I\'m working on a prolog algorithm that will perform a \"swap\" on a list.

Example:

Input: [1,2,3,4] -> Output: [3,4,1,2] Input: [1,2,3,4,5] -> Output: [4,5,3,1

4条回答
  •  醉酒成梦
    2021-01-27 07:39

    an idiomatic solution:

    swap(L,S) :-
        %maplist(when_, [
        append([X,C,Y],L), (C=[];C=[_]), same_length(X,Y),
        reverse(X,U), reverse(Y,V), append([U,C,V],S)
        %])
        .
    
    ?- swap([1,2,3,4,5],S).
    S = [2, 1, 3, 5, 4] ;
    false.
    

    it's not a true relation, since it hangs if called in mode swap(-,+), but it behaves better after uncommenting the bracketing, and providing this snippet:

    :- meta_predicate when_(0).
    when_(P) :-
        strip_module(P,_,Q), Q =.. [_|As],
        or_list(As, Exp), display(Exp),
        when(Exp, P).
    
    or_list([A], ground(A)) :- !.
    or_list([A|As], (ground(A);Exp)) :- or_list(As, Exp).
    

    edit

    after @false' comments, I'm trying to explain the motivation of this answer. The requested swap/2 'function' seems to be an ideal candidate to showcase the peculiarity of Prolog data model, albeit the requested explanation (about proper syntactic usage of integer arithmetic applied to lists) is not even hinted here.

    From the very start of Prolog we have available an unique mixing of relational and functional (recursive) tools, that could make little sense to a newbie. At least, it still surprises me... and I like this fact.

    Now, functional logic programming, for instance Curry, attempts a solution through 'narrowing'. From the linked page:

    Narrowing is useful because it allows a function to be treated as a relation: its value can be computed "in both directions"

    Now, when_/1 it's a simple minded approach to the same problem. Down to earth, the swap/2 has been described as a function, but could be implemented as a relation ?

    @false suggestion, adding same_length(L,S) as first goal, fixes the swap(-,+) mode, but loops on swap(-,-). The approach based on when_/1 instead reports the inability to ground the conjunction.

    edit

    Termination issues apart, my choice of goals order is really ineffective. Hinting this answer to another question, occurred to me that a big efficiency gain (at least, for the mode swap(+,-)) can be obtained putting constraints first:

    3 ?- numlist(1,100,L), time((append([X,C,Y],L), (C=[];C=[_]), same_length(X,Y), append([Y,C,X], S))). 
    % 328,899 inferences, 0.125 CPU in 0.125 seconds (100% CPU, 2634422 Lips)
    L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
    X = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
    C = [],
    Y = [51, 52, 53, 54, 55, 56, 57, 58, 59|...],
    S = [51, 52, 53, 54, 55, 56, 57, 58, 59|...] 
    .
    
    4 ?- numlist(1,100,L), time(((C=[];C=[_]), same_length(X,Y), append([X,C,Y],L), append([Y,C,X], S))). 
    % 3,273 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 3210999 Lips)
    

提交回复
热议问题