Nessya Nakache
Nessya Nakache

Reputation: 11

converting a list into an integer in prolog?

As practice in prolog, I am trying to convert a list of integers into one whole number as in if we have a list [1,2,3] then it outputs 123. This is what I've wrote for the moment:

listToNum([],_).
listToNum([H|T],Num):-
    cntSize(T,Size),
    N1 is Num + (H*10**Size),
    listToNum(T,N1).

and I received this comment from the program:

Arguments are not sufficiently instantiated
In:
   [2] _1626 is _1632+1* ...
   [1] listToNum([1,2],_1696) at  line 33

What can I do to improve my code and receive the appropriate results please?

Upvotes: 0

Views: 701

Answers (4)

Markus Weninger
Markus Weninger

Reputation: 12668

I think the answer by @slago is exactly what you are looking for.

If you are also interested in a solution using SWI-Prolog predicates instead of "hand-written recursion" (using the predicates specifically reverse, findall, nth0 and sum_list), here you go. I added comments to highlight what happens for each predicate for your given example:

list_to_num(L, R) :-                                           % L = [1, 2, 3] 
  reverse(L, LRev),                                            % LRev = [3, 2, 1],
  findall(Part, (nth0(I, LRev, M), Part is M*(10**I)), Parts), % Parts = [3, 20, 100],
  sum_list(Parts, R).                                          % R = 123

PS: I also suggest the recursive solution, this answer exists purely to showcase another solution.

PPS: CapelliC's solution using the SWI-Prolog predicates atomic_list_concat and atom_number is also much more clean than my solution. I will still keep my answer undeleted to have something to laugh at in a few years.

Upvotes: 0

CapelliC
CapelliC

Reputation: 60034

SWI-Prolog is geared toward practical idioms, so here is another solution, based on specific builtin:

listToNum(L,N) :- atomic_list_concat(L,A),atom_number(A,N).

Test:

?- listToNum([1,2,3],N).
N = 123.

Upvotes: 1

slago
slago

Reputation: 5519

You can improve your code, by avoiding calculating the length of lists and also using tail recursion, as follows.

list_to_num(L, N) :-
    list_to_num(L, 0, N).

list_to_num([], A, A).
list_to_num([H|T], A, N) :-
    B is 10*A + H,
    list_to_num(T, B, N).

Examples:

?- list_to_num([3,9,7,0],N).
N = 3970.

?- list_to_num([1,2,3],N).
N = 123.

?- list_to_num([1],N).
N = 1.

?- list_to_num([],N).
N = 0.

Upvotes: 1

Zebollo
Zebollo

Reputation: 1

The "is/2" operator is not associative, so right side must be a closed term. This means that every variable on the right side must be bound to a number at call time. That is not the case for "Num".

Your implementation is defective. Try this:

list2numberV1(L,N) :-
    reverse(L,RevL),
    list2numberV1_aux(RevL,N).

list2numberV1_aux([],0).

list2numberV1_aux([H|T],N) :-
     list2numberV1_aux(T,TailNum),
     N is H+(TailNum*10).

Or this:

list2numberV2([],0).
list2numberV2([N],N) :- !.
list2numberV2([H|T],N) :-
    list2numberV2(T,TailNum),
    length(T,TailLength),
    N is TailNum+(H*(10**TailLength)).

Upvotes: 0

Related Questions