简体   繁体   中英

Prolog Create a List

I have to create list of n elements for example,

do_list(5,L1).

should return,

L1=[1,2,3,4,5].

This is what I have, but it's not working.

do_list(X,L1):- X1 is X-1, do_list(X1,[X1|L1]).

do_list(0,[]).

If you want to create a list of consecutive numbers from 1 to N you can use builtin predicates findall/3 and between/3 this way:

do_list(N, L):- 
  findall(Num, between(1, N, Num), L).

?- do_list(5,L).
L = [1, 2, 3, 4, 5].

SWI also has another builtin which does just that, numlist/3 :

?- numlist(1,5,L).
L = [1, 2, 3, 4, 5].

There are three problems with your code. The first problem is that you add X1 to the list in the clause body, but you never pass the new list back towards the head of the clause. Ie, L1 is an accumulator variable, but you need a third argument that will be bound to the final list.

The second is that the second clause only matches if the input list is empty. This will never be the case, since you add X1 to the list before calling do_list/2 recursively. Ie, you don't have a recursion anchor, and the goal ?- do_list(5,L) will never return.

The third problem is that you add X1 to the list instead of X. You'd skip the largest number.

This is how it should work:

do_list(N, L) :- do_list1(N, [], L).

do_list1(0, L, L) :- !.
do_list1(N, R, L) :- N > 0, N1 is N-1, do_list1(N1, [N|R], L).

Or if you don't want to use any built-in function (like me, when I tried this as a practice and then run into this question), you can use this (working but not effective) solution:

connect([],X,X).
connect([H|T],C,[H|T2]) :- connect(T,C,T2).

revert([],[]).
revert([H|T],R) :- revert(T,Trev), connect(Trev,[H],R)

do_revlist(0,[]).
do_revlist(X,[X|L]) :- X1 is X-1, do_revlist(X1,L).
do_list(X,L2) :- do_revlist(X,L), revert(L,L2).

PS Works only for positive integers.

Another solution similar to that of twinterer but without cut or predefined predicates, employing an accumulator.

do_List(Max,L) :- do_ListAcc(1,Max,L). % call Accumulator

do_ListAcc(N,N,[N]). % N=:=N ends recursion
do_ListAcc(Min,Max,[Min|Succs]) :-
    Next is Min + 1,
    do_ListAcc(Next,Max,Succs).

This also works only for positive integers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM