E. Christian
E. Christian

Reputation: 21

Prolog: Swapping two halves of a list

I am writing a predicate in prolog that will break a list with an even number of variables into two halves and swap them. For example [a,b,c,d] --> [c,d,a,b].

append([], List, List).
append([Head|Tail], List, [Head|Rest]) :- 
   append(Tail, List, Rest).

divide(L, X, Y) :-
   append(X, Y, L),
   length(X, N),
   length(Y, N).

swap([], []).
swap([A], D) :-
   divide(A, B, C),
   append(C, B, D).

I would expect this to work by dividing [A] into two smaller equal sized lists, then appending them together in the reverse order, and then assigning the variable "D" to the list.

What I am getting is "false", why does this not work?
I'm very new to prolog so this might be a silly/simple question, thanks!

Upvotes: 2

Views: 654

Answers (2)

false
false

Reputation: 10102

Your question is why swap([a,b,c,d],[c,d,a,b]) fails. And here is the actual reason:

?- swap([_/*a*/,_/*b*/|_/*,c,d*/],_/*[c,d,a,b]*/).

:- op(950, fy, *).
*(_).

swap([], _/*[]*/).
swap([A], D) :-
   * divide(A, B, C),
   * append(C, B, D).

So, not only does your original query fail, but even this generalization fails as well. Even if you ask

?- swap([_,_|_],_).
   false.

you just get failure. See it?

And you can ask it also the other way round. With above generalization, we can ask:

?- swap(Xs, Ys).
   Xs = []
;  Xs = [_A].

So your first argument must be the empty list or a one-element list only. You certainly want to describe also longer lists.

Upvotes: 2

Prashu Gupta
Prashu Gupta

Reputation: 109

Maybe this helps

:- use_module(library(lists), []).

 divide(L, X, Y) :-
 append(X, Y, L),
 length(X, N),
 length(Y, N).

 swap([], []).
 swap(L, D) :-
 divide(L, B, C),
 append(C, B, D).

Upvotes: 0

Related Questions