Given a list of numbers, returns a list such that the numbers in the input are replaced by the result of num2list,

I’m using: SWI-Prolog version 8.0.1

I am new in prolog so please don’t be to strict. I want to write a prolog program that given a list of numbers, returns a list such that the numbers in the input are replaced by the result of num2list, when they are followed by a bigger number, and otherwise skipped. When the list has only one number, this should also be replaced with the result of num2list. For example, if the input is [2,4,1,3,4,3,2,1], the result is [[0,1,2],[0,1],[0,1,2,3],[0,1]].

Any help would be appreciated.

Also could anyone suggest a good prolog tutorial?

I think maplist/3 will be what you want: http://www.swi-prolog.org/pldoc/doc_for?object=maplist/3 (e.g. ?- maplist(num2list, Input, Output).)

For tutorials, Annie’s tutorials here were my introduction. Markus Triska’s stuff here is also very good.

Thank you for your reply James. If i want to implement it without maplist. How can i do that?

You can using the listing/1 predicate to see the source of a predicate; e.g.,

listing(maplist/3).
:- meta_predicate apply:maplist(2,?,?).

apply:maplist(Goal, List1, List2) :-
    maplist_(List1, List2, Goal).

true.

?- listing(maplist_/3).
apply:maplist_([], [], _).
apply:maplist_([Elem1|Tail1], [Elem2|Tail2], Goal) :-
    call(Goal, Elem1, Elem2),
    maplist_(Tail1, Tail2, Goal).

true.

From that then, we can see that the equivalent code without maplist will look like this:

num2list_each([], []).
num2list_each([Num|NumRst], [NumList|NumListRst]) :- 
   num2list(Num, NumList),
   num2list_each(NumRst, NumListRst). 

Sorry for my stupidness but how sample call will look like in this case?

No problem! After defining the above num2list_each/2 predicate, as well as num2list/2, you would use it like so:

?- num2list_each([2, 4, 1, 3], Out).
Out = [[0,1,2], [0,1,2,3,4], [0, 1], [0, 1, 2, 3]]
true.

I know this doesn’t answer your question, but I strongly recommend “The Art of Prolog” by Sterling and Shapiro. It is much better than the tutorials I have found online. The book’s website now has a download link for the complete PDF.

It depends how deep you want to go, but the book is beginner-friendly, thorough, and well written. You don’t have to read it to the very end to make good use of it.

IDK why i get these errors:
ERROR: Undefined procedure: num2list/2
ERROR: In:
ERROR: [9] num2list(2,_3284)
ERROR: [8] num2list_each([2,4|…],[_3326|_3328]) at c:/users/user/desktop/prolog/prolog-examples-master/num2list2.pl:3
ERROR: [7]

Thank you for your reply Boris. And thank you for your book suggestion. I will take a look. Hope it will help.

The stuff I wrote was assuming you’d already defined num2list, that error is indicating that you haven’t done so yet.

Once upon a time, findall/3, was the swiss knife of basic list processing. Coupled with nondeterministic accessors (like member/2, between/3, nth1/3, arg/3, append/3, etc etc) it provide common functionality in a fairly efficient and compact way.

for instance,

 num2list(N,Ns) :- findall(I, between(0,N,I), Ns).

oops, first time I use Discourse’ editor, I wrongly hit enter … let’s continue

num2list_each(Ns,Ls) :- 
    findall(L, (append(_, [A,B|_], Ns), A<B, num2list(A,L)), Ls).

?- num2list_each([2,4,1,3,4,3,2,1],Ls).
Ls = [[0, 1, 2], [0, 1], [0, 1, 2, 3]].

There is an obvious bug, wrt the missing num2list of the last element. Next we’ll see how to fix that, refining the goal that is executed by findall/3, the 2nd argument.

Well, now correcting the bug about the last element, hope you can see the pattern…

num2list_each(Ns,Ls) :-
    findall(L, (append(_,T,Ns),
            (T=[A,B|_], A<B ; T=[A]),
            num2list(A,L)), Ls).

num2list(N,Ns) :-
    findall(I, between(0,N,I), Ns).