Kaan Akdik
Kaan Akdik

Reputation: 35

Listing elemets of a list as i want, in Prolog

This is my list in Prolog:

myList([a,b,c,d,e]).

I am trying to write a predicate. That predicate should give me this result:

ab
ac
ad
ae
bc
bd
be
cd
ce
de

I found a solution that's near to my goal. But it is not exactly what I want.

?- L=[a,b,c], findall(foo(X,Y), (member(X,L),member(Y,L)), R).

L = [a, b, c],

R = [foo(a, a), foo(a, b), foo(a, c), foo(b, a), foo(b, b), foo(b, c), foo(c, a), foo(c, b), foo(..., ...)].

For example i dont want to aa or bb or cc. Also, there is already ac result. So i dont want to again ca.

Sorry for my English. Thanks.

Upvotes: 0

Views: 1104

Answers (3)

false
false

Reputation: 10102

?- set_prolog_flag(double_quotes, chars).
   true.
?- List = "abcde",
   bagof(X-Y, Pre^Ys^( append(Pre, [X|Ys], List), member(Y,Ys) ), XYs).
   List = "abcde", XYs = [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e].
?- List = [A,B,C,D,E],
   bagof(X-Y, Pre^Ys^( append(Pre, [X|Ys], List), member(Y,Ys) ), XYs).
   List = [A,B,C,D,E], XYs = [A-B,A-C,A-D,A-E,B-C,B-D,B-E,C-D,C-E,D-E].

From your question it is not that evident what you want but it seems you are happy to use findall/3. Above solutions use bagof/3 which is a somewhat more civilized version of findall/3. bagof/3 takes into account variables, and thus you get the same result with concrete characters [a,b,c,d,e] or with a list of variables [A,B,C,D,E].

You have used terms foo(a,b), in such situations it is more common (and convenient) to say a-b.

Upvotes: 3

false
false

Reputation: 10102

Here is another solution that does not need any of the higher-order predicates.

:- set_prolog_flag(double_quotes, chars).
:- use_module(library(double_quotes)).

list_pairwise([], []).
list_pairwise([E|Es], Fs0) :-
   phrase(values_key(Es, E), Fs0,Fs),
   list_pairwise(Es, Fs).

values_key([], _K) --> [].
values_key([V|Vs], K) -->
   [K-V],
   values_key(Vs, K).

?- list_pairwise("abcde", KVs).
   KVs = [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e].
?- list_pairwise(L, [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e]).
   L = "abcde"
;  false.
?- list_pairwise(L, [A-B,A-C,A-D,A-E,B-C,B-D,B-E,C-D,C-E,D-E]).
   L = [A,B,C,D,E]
;  false.
?- KVs = [K1-_,K1-_,K2-_|_], dif(K1,K2), list_pairwise(Ks,KVs).
   KVs = [K1-K2,K1-_A,K2-_A], Ks = [K1,K2,_A], dif:dif(K1,K2)
;  false.

In the last query we show that a sequence starting with keys, K1, K1, K2 can only result in the sequence of three elements.

Upvotes: 3

max66
max66

Reputation: 66200

What about a couple of predicates as follows ?

printCouples(_, []).
printCouples(E1, [E2 | T]) :-
  write(E1), write(E2), nl,
  printCouples(E1, T).

printList([]).
printList([H | T]) :-
  printCouples(H, T),
  printList(T).

From

printList([a, b, c, d])

you get

ab
ac
ad
bc
bd
cd

Upvotes: 1

Related Questions