Create list - geometric progression

I would like to create a list of geometric progressions using a predicate with 4 parameters - the list in which the progression will be generated, the length of this list, the starting element and the multiplier of the progression. What I have done so far only has a three parameter predicate to generate a geometric progression without stopping:

gengeom([X],X,_).
gengeom([H|Tail],H,Q):-X is H*Q,gengeom(Tail,X,Q).

      

And this query gives me all progressions with an initial element of 1 and a multiplier of 2:

?-gengeom(L,1,2),write(L),nl,fail.

      

Can anyone help me write a 4-parameter predicate that I really would like to have (which stops generating more numbers after the length of the list has become a certain number)?

+3


source to share


3 answers


just adding a countdown parameter will work and keep the nice generating property of your code:

gengeom([X],X,_,_).
gengeom([H|Tail],H,Q,N) :- N>1, M is N-1, X is H*Q, gengeom(Tail,X,Q,M).

?- gengeom(L,1,2,3).
L = [1] ;
L = [1, 2] ;
L = [1, 2, 4] ;
false.

      

of course you could get a slightly more compact, using findall / 3, Prolog list generator:



gengeom(L,H,Q,N) :-
    findall(V, (between(H,N,M), V is Q**(M-1)), L).

      

but this snippet (similar to @ joel76's post) will only create the "final" list ...

+6


source


With SWI-Prolog you can write:

:- use_module(library(lambda)).

gengeom(Len, Start, Multiplier, L) :-
    length(L, Len),
    foldl(\X^Y^Z^(X = Y,
                 Z is Y * Multiplier),
          L, Start, _).

      



For example:

?- gengeom(5, 1, 2, L).
L = [1, 2, 4, 8, 16].

      

+5


source


Well, as you asked, including the length parameter, you need to update the stop condition to be true when the length of the list is one, and the general suggestion is to decrease that length at each step.
The predicate gengeom/4

will now look like this:

gengeom([X], X ,_, 1):- !.
gengeom([H|Tail], H, Q, N):-N > 0, X is H * Q, N1 is N - 1, gengeom(Tail, X, Q, N1).

      

Find a progression with start 1, multiplier 2 and length 5

?- gengeom(L, 1, 2, 5).
L = [1, 2, 4, 8, 16]

      

You can find all solutions from length 1 to selected length using metapredicate findall/3

:

findall(L, (member(N, [1,2,3,4,5]), gengeom(L,1,2, N)), R).

      

This should be complete:

gengeom([X], X ,_, 1):- !.
gengeom([H|Tail], H, Q, N):-N > 0, X is H * Q, N1 is N - 1, gengeom(Tail, X, Q, N1).

generate(Start, Step, Stop):- findall(L, (numlist(1,Stop, Len), member(N, Len), gengeom(L,Start,Step, N)), R), writeGen(R).

writeGen([]).
writeGen([H|Tail]):- write(H), nl, writeGen(Tail).

      

Test

?- generate(1, 2, 5).
[1]
[1, 2]
[1, 2, 4]
[1, 2, 4, 8]
[1, 2, 4, 8, 16]
true

      

0


source







All Articles