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
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)