Create a list of value pairs from 0 to n-1 in lexicographic order

I am making a program with the result Result is a pair of values ​​[X, Y] between 0 and N-1 in lexicographic order

I have this right now:

pairs(N,R) :-
   pairsHelp(N,R,0,0).

pairsHelp(N,[],N,N) :- !.
pairsHelp(N,[],N,0) :- !.
pairsHelp(N,[[X,Y]|List],X,Y) :-
    Y is N-1,
    X < N,
    X1 is X + 1,
    pairsHelp(N,List,X1,0).
pairsHelp(N,[[X,Y]|List],X,Y) :-
    Y < N,
    Y1 is Y + 1,
    pairsHelp(N,List,X,Y1).

      

I get what I want the first iteration, but Prolog keeps going and then gives me a second answer.

?-pairs(2,R).
R = [[0,0],[0,1],[1,0],[1,1]] ;
false.

      

I don't need the second answer (false), only the first. I want him to stop after he found the answer. Any ideas?

+3


source to share


2 answers


Keep in mind that there is a much easier way to get what you want. If in fact both X and Y must be integers, use between/3

to enumerate integers ("lexicographic" here is the same as the order of natural numbers: 0, 1, 2, ... This is the order in which it between/3

lists possible solutions if the third argument is a variable):

pairs(N, R) :-
    succ(N0, N),
    bagof(P, pair(N0, P), R).

pair(N0, X-Y) :-
    between(0, N0, X),
    between(0, N0, Y).

      

And then:

?- pairs(2, R).
R = [0-0, 0-1, 1-0, 1-1].

?- pairs(3, R).
R = [0-0, 0-1, 0-2, 1-0, 1-1, 1-2, 2-0, 2-1, ... - ...].

      

I use the usual Prolog way of representing a pair X-Y

(in canonical form:) -(X, Y)

instead of [X,Y]

(canonical form:) .(X, .(Y, []))

.

The nice thing about this program is that you can easily rewrite it to work with a different "alphabet" of your choice.

?- between(0, Upper, X).

      



semantically equivalent to:

x(0).
x(1).
% ...
x(Upper).

?- x(X).

      

For example, if we had an alphabet consisting of b

, a

and c

(in that order!):

foo(b).
foo(a).
foo(c).

foo_pairs(Ps) :-
    bagof(X-Y, ( foo(X), foo(Y) ), Ps).

      

and then:

?- foo_pairs(R).
R = [b-b, b-a, b-c, a-b, a-a, a-c, c-b, c-a, ... - ...].

      

The order of sentences foo/1

determines the order of your alphabet. The conjunction, foo(X), foo(Y)

together with the order X-Y

in the pair, determines the order of the pairs in the list. Try to write, for example, bagof(X-Y, ( foo(Y), foo(X) ), Ps)

to find out what the order of the pairs in Ps

.

+4


source


Use combined with lambda !

?- use_module(library(lambda)).

      

In conjunction with init0/3

and xproduct//2

("cross product") just write:

?- init0(=,3,Xs), phrase(xproduct(\X^Y^phrase([X-Y]),Xs),Pss).
Xs = [0,1,2], Pss = [0-0,0-1,0-2,1-0,1-1,1-2,2-0,2-1,2-2].

      



How about something more general? How about other meanings N

?

?- init0(=,N,Xs), phrase(xproduct(\X^Y^phrase([X-Y]),Xs),Pss).
  N = 0, Xs = [],          Pss = []
; N = 1, Xs = [0],         Pss = [0-0]
; N = 2, Xs = [0,1],       Pss = [0-0,0-1,
                                  1-0,1-1]
; N = 3, Xs = [0,1,2],     Pss = [0-0,0-1,0-2,
                                  1-0,1-1,1-2,
                                  2-0,2-1,2-2]
; N = 4, Xs = [0,1,2,3],   Pss = [0-0,0-1,0-2,0-3,
                                  1-0,1-1,1-2,1-3,
                                  2-0,2-1,2-2,2-3,
                                  3-0,3-1,3-2,3-3] 
; N = 5, Xs = [0,1,2,3,4], Pss = [0-0,0-1,0-2,0-3,0-4,
                                  1-0,1-1,1-2,1-3,1-4,
                                  2-0,2-1,2-2,2-3,2-4,
                                  3-0,3-1,3-2,3-3,3-4,
                                  4-0,4-1,4-2,4-3,4-4]
...

      

Does it work for other terms too? How about the order? Consider @ Boris's case used in his answer :

?- phrase(xproduct(\X^Y^phrase([X-Y]),[b,a,c]),Pss).
Pss = [b-b,b-a,b-c,a-b,a-a,a-c,c-b,c-a,c-c].  % succeeds deterministically

      

+2


source







All Articles