Reputation: 11
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
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
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
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
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