Generate list - geometric progression

不羁岁月 提交于 2019-12-22 10:49:15

问题


I'd like to generate a geometric progression list using a predicate with 4 parameters - the list where the progression will be generated, the length of this list, the start element, and the multiplier of the progression. What I've done so far is having only a 3-parameter predicate to generate the 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 start element 1 and multiplier 2 :

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

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


回答1:


just adding a countdown parameter will work, and will preserve the nice generative 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 somewhat more compact using findall/3, the 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' post) will build just the 'final' list...




回答2:


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].



回答3:


Well, as you asked, including the length parameter you need update your stop condition to be true when the length of the list is one, and the general clause, must decrement this length on each step.
Now gengeom/4 predicate will 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).

This find the 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 the selected length, using the 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


来源:https://stackoverflow.com/questions/31225617/generate-list-geometric-progression

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!