0

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.

false
  • 10,264
  • 13
  • 101
  • 209
Kaan Akdik
  • 35
  • 7

3 Answers3

3
?- 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.

false
  • 10,264
  • 13
  • 101
  • 209
  • Elegant, elegant. I have allowed myself to steal this in order to add a note at the findall page of SWI Prolog doc. – David Tonhofer Jan 12 '20 at 14:41
  • Also, the printout of `XYs` will be truncated unless `set_prolog_flag(answer_write_options, [quoted(true), portray(true), max_depth(100)]).` – David Tonhofer Jan 12 '20 at 14:43
  • I agree with these two indentations, but not with the max depth, nor the other SWI-related links. SWI does not even implement `bagof/3` nor `findall/3` correctly. – false Jan 12 '20 at 14:43
  • Thanks, but any more info on the wrong implementation of bagof/findall for SWI Prolog? Or, in which implementation are they correct? – David Tonhofer Jan 12 '20 at 14:45
  • 1
    SICStus is fine. Whereas in SWI, `findall(t,(repeat,fail),1)` should produce a `type_error(list,1)` but it rather loops. – false Jan 12 '20 at 14:51
  • And `max_depth(0)` is my setting for SICStus – false Jan 12 '20 at 14:52
  • @David: As for elegance, please refer to the other answer. This here loops for problematic cases (which is still much better than having incorrect answers). – false Jan 12 '20 at 15:09
3

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.

false
  • 10,264
  • 13
  • 101
  • 209
1

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
false
  • 10,264
  • 13
  • 101
  • 209
max66
  • 65,235
  • 10
  • 71
  • 111