Related
This question already has answers here:
Prolog converting integer to a list of digit
(6 answers)
Closed 1 year ago.
I wrote a Prolog predicate which transforms a list of digits in a number. So, for example, if the input is the list [1, 2, 3] then the output will be the number 123. This is my code:
convertListToNum([], Col, Col).
convertListToNum([H|T], Col, R):-
Col2 is Col * 10 + H,
convertListToNum(T, Col2, R).
convertListToNumMain(L, R):-
convertListToNum(L, 0, R).
As you can see, the arguments of the predicate are L=input, R=output, since I provide the list L as input into ConvertListToNumMain and I will get as output the number in R. If I try this predicate, it works as expected: convertListToNumMain([1, 2, 3], R) will give as output R=123.
Now what I want to do is use this function by providing the output number instead of the input list. I will use L=output, R=input. So I will not provide the list L anymore, I will provide the number R and expect to receive the list as output. So what I want is to call this: convertListToNumMain(L, 123) and I expect to receive as output L=[1, 2, 3]. However, when I call this I get the error Arguments are not sufficiently instantiated. I assume it is because in the line Col2 is Col * 10 + H I try to work with the first element of the list even tough the list is not instantiated, but I am not sure. What can I do to make this work?
I want to convert a list of digits to a number and then the number back to a list of digits and I thought I could get away with this, but apparently not. The alternative is to create another complex and inefficient predicate which will at each step find the most significant digit of a number, then add it to the list, find that number without that most significant digit and then make the next call. Or at least that is my idea. That is a lot of code and (it seems to me) more inefficient. So is there any way I can use what I already have by providing the output? If not, is there a better way than my idea above to convert a number into a list of digits (recursively, of course, since I'm using Prolog)?
It's not that complicated. Or inefficient.
int_list( N , Ds ) :- nonvar(N), number_to_digits(N,Ds).
int_list( N , Ds ) :- nonvar(Ds), digits_to_number(Ds,0,N).
digits_to_number( [] , N , N ) .
digits_to_number( [D|Ds] , T , N ) :-
T1 is 10 * T + D ,
digits_to_number(Ds,T1,N).
number_to_digits( 0 , [0] ).
number_to_digits( N , Ds ) :-
N > 0,
digits(N, [], Ds).
digits( N , T , Ds ) :-
N > 0,
D is N mod 10,
N1 is N div 10,
digits(N1,[D|T],Ds).
digits( 0 , Ds , Ds ) .
But it might be easier to use built-in predicate number_codes/2:
int_digits( N , Ds ) :- nonvar(Ds) , codes_digits(Cs,Ds) , number_codes(N,Cs) .
int_digits( N , Ds ) :- nonvar(N) , number_codes(N,Cs) , codes_digits(Cs,Ds) .
codes_digits( [] , [] ) .
codes_digits( [C|Cs] , [D|Ds] ) :- code_digit(C,D), codes_digits(Cs,Ds).
code_digit(C,D) :- nonvar(C), D is C-48.
code_digit(C,D) :- nonvar(D), C is D+48.
I'm new to Prolog and I'm facing some exercises, this one for example ask me to write a predicate histogram/1 to take a list as argument and print an horizontal histogram with the occurrences of numbers 0..9 in the list. For example:
?- histogram([1,3,4,1,1,4,7]).
0
1 ***
2
3 *
4 **
5
6
7 *
8
9
true.
My program is the following, and works as requested, but I've a doubt: as you can see I used cut predicate and semicolon in that way (first line), only to obtain TRUE after the histogram (just to fit the example provided, I don't really care about it!), if you omit this you'll get always FALSE as N<10 will fail...
My question is: is this a proper way to use the cut predicate? If not, how could I improve my program (any other suggestion will be appreciated)?
histogram(X):-
valid(X),
( print(0,X)
; !
).
print(N,X):-
write(N) , tab(2), count(N,X) , nl,
N1 is N+1,
N1 < 10 ,
print(N1,X).
count(_,[]).
count(E,[E|C]):-
write('*') ,
count(E,C).
count(E,[Y|C]):-
E\=Y ,
count(E,C).
valid([]).
valid([X|T]):-
integer(X),
X>=0,
X<10,
valid(T).
maybe
print(N,X):- N < 10, write(N), tab(2), count(N,X), nl, N1 is N+1, print(N1,X).
print(10,_).
and the whole program can be made much shorter using SWI-Prolog library, for instance
histogram(X) :-
forall(between(0,9,N), (findall(*,member(N,X),H), format('~d ~s~n', [N, H]))).
I am a noob prolog programmer and facing a difficulty with one of the basic problems that have been given in the book where I am learning from. The question. The question basically asks us to write down a Prolog procedure that takes two lists as arguments, and succeeds if the first list is twice the size of the second list and the two lists start with the same element. The procedure should return false if the two lists are empty.
For example it should return true if we pass the query:
a2b([a,a,a,a],[a,b]).
and would fail with a query like:
a2b([a,a],[a,b,b,b]).
I don't know how to solve this problem recursively, any help would be appreciated. Thanks!
First, the request about lengths:
/* empty list fulfills request */
a2b_length([],[]).
/* non-empty: discard two elements of first list,
one of second list, and verify
remainder */
a2b_length([_,_|Q1],[_|Q2]) :-
a2b_length(Q1,Q2).
Now, we can add the requirement "starts by the same term and are non empty", and write the last clause:
a2b([X,_|Q1],[X|Q2]) :-
a2b_length(Q1,Q2).
Cute problem. It can be solved using the following code:
% fail of the first element of each list don't unify
% or if one or both lists are empty
a2b([First| List1], [First| List2]) :-
% calculate the length of the second list
% while traversing both lists in parallel
a2b_first(List2, 1, N, List1, Rest1),
% check that the length of the rest of the first
% list is equal to the length of the second list
a2b_second(Rest1, N).
a2b_first([], N, N, Tail1, Tail1).
a2b_first([_| Tail2], N0, N, [_| Tail1], Rest1) :-
N1 is N0 + 1,
a2b_first(Tail2, N1, N, Tail1, Rest1).
a2b_second([], 0).
a2b_second([_| Tail1], N) :-
M is N - 1,
a2b_second(Tail1, M).
Of course, there's a simpler (but not as fun to code!) solution:
% fail of the first element of each list don't unify
% or if one or both lists are empty
a2b([First| List1], [First| List2]) :-
length([First| List1], N1),
length([First| List2], N2),
N1 is 2 * N2.
The length/2 predicate is usually available either as a built-in predicate or as a library predicate.
For learning Prolog, studying the first solution is interesting. For example, it exemplifies how to take advantage of first-argument indexing and how to use accumulators for writing predicates that are tail-recursive (and thus space efficient).
Also, the first solution can be more efficient than the second solution. In the second solution, we always traverse both lists to the end to find their lengths. But, in the first solution, that is not always necessary.
Don't overthink things: just describe the solution and let Prolog sort it out.
The solution doesn't require counting or predicates other than its trivial self. It's all pattern matching. We have a special (terminating case), asserting that a list of length 2 is twice as long as a list of length 1 (which should be pretty obvious):
is_twice_as_long_as( [_,_] , [_] ) .
Then there is the general case, which asserts that given two lists of arbitrary length, the left is twice as long as the right IF we can (A) remove 2 items from the left, (B) remove 1 item from right, and recursively assert that their respective remainders are likewise twice as long:
is_twice_as_long_as( [_,_|A] , [_|B] ) :- is_twice_as_long_as( A , B ) .
Giving us the finished product:
is_twice_as_long_as( [_,_] , [_] ) .
is_twice_as_long_as( [_,_|A] , [_|B] ) :- is_twice_as_long_as( A , B ) .
Easy!
Edited to note the requirement that the two lists begin with the same element:
Depending on how that is interpreted...
this requires that the lists have a common head on each iteration:
is_twice_as_long_as( [A,_] , [A] ) .
is_twice_as_long_as( [A,_|L] , [A|R] ) :- is_twice_as_long_as( L , R ) .
this does the check for a common head just once::
is_twice_as_long_as( [A|As] , [A|Bs] ) :-
is_2x([A|As],[A|Bs]) .
is_2x( [_,_] , [_] ) .
is_2x( [_,_|L] , [_|R] ) :- is_2x( L , R ) .
How to implement flatten list in prolog ,with tail recursion ?
This is code for flatten/2 with simple recursion (that is mean without back-tracking):
flatten([], []).
flatten([L|Ls], FlatL) :-
!,
flatten(L, NewL),
flatten(Ls, NewLs),
append(NewL, NewLs, FlatL).
flatten(L, [L]).
?- flatten([1, [2,3], [4]], X).
X=[1,2,3,4].
I'm trying to do the same algorithm but with tail recursion (Accumulator). For exemple, the predicate sum/2 returns the addition of all member of the list, with backtracking:
sum([X],[X]).
sum([H|T],S) :- sum(T,S1), S is H + S1 .
the same algo with tail recursion is
sum1(L,S) :- sum1(L,0,S).
sum1([],Acc,Acc).
sum1([H|T],Acc,S) :- Acc1 is Acc+H, s(T,Acc1,S).
You might want to read up on tail recursion optimization
What Is Tail Call Optimization?
https://en.wikipedia.org/wiki/Tail_recursion
Tail recursion optimization/elimination has little to nothing to do with accumulators. It has to do with whether or not the current frame on the call stack can be reused. If it can, the recursive call is effectively converted into iteration. If it can't be reused, a new frame has to be pushed on the stack with the nasty side effect that [eventually] you will throw a stack overflow exception.
This is tail recursive and gets optimized into iteration:
write_list( [] ) .
write_list( [X|Xs] ) :-
write(X),nl,
write_list(Xs).
This is not:
factorial(1,1) .
factorial(N,F) :-
N > 1 ,
N1 is N-1 ,
factorial(N1,F1) ,
F is N1+F1 .
The difference is that in the former, no use is made of anything local following the recursive call, and so the stack frame can be reused. In the latter, the contents of the stack frame must be preserved, and so a new stack frame must be allocated for the recursive call.
However, the following should do the job for you.
flatten( Xs , Fs ) :- % to flatten a list of via an accumulator...
flatten( Xs , [] , Rs ) , % - invoke the worker predicate with the accumulator seeded as the empty list.
reverse(Rs,Fs) % - since the flattened list will be built in reverse order, you'll need to reverse it after all the work is done.
.
flatten( [] , Fs , Fs ) . % if the source list is exhausted, our work is done.
flatten( [X|Xs] , Ts , Fs ) :- % otherwise...
is_list(X) , % - if the head of the list is itself a list
! , % - eliminate the choice point.
flatten(X,Ts,T1) , % - flatten the sublist by invoking the worker predicate on the sublist
flatten(Xs,T1,Fs) % - and then continue
. %
flatten( [X|Xs] , Ts , Fs ) :- % finally, the list head must be unbound or some other non-list thing.
flatten(Xs,[X|Ts],Fs) % - prepend it to the accumulator and continue.
. %
is_list( X ) :- var(X) , ! , fail . % unbound variables are manifestly not lists.
is_list( [] ) . % but the empty lislt is.
is_list( [_|_] ). % and so is a non-empty list.
You should note that it's not completely tail recursive. Every time a nested list is encountered, it's got to save the current state, so it can continue from where it left off after the recursive call to flatten the sublist.
Hello I have to solve some prolog problems with lists but i can't figure it out how these work.
I have to add "1" after every even element in a list, and to make the difference of 2 lists.
I know this seems easy, in other language like java or c# i would make it very easy, but prolog it's giving me headaches.
Please help me :|
Edited to note the clarified problem statement ("even item" meaning the item's value is even (rather than the item's ordinal position within the list):
insert_one_after_even_items( [] , [] ). % if the source list is exhaused, we're done.
insert_one_after_even_items( [X|Xs] , [X,1|Ys] ) :- % otherwise,
0 is X mod 2 , % - if the number is even, prepend it and a 1 to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. %
insert_one_after_even_items( [X|Xs] , [X|Ys] ) :- % otherwise,
1 is X mod 2 , % - if the number is odd, prepend it to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. % Easy!
For your second problem, producing the difference between two lists, are you talking about set differences? If so, given two sets A and B, are you talking about the relative difference (all elements of A that do not exist in B), or the absolute difference (all elements of either A or B that do not exist in both sets)?
To solve the relative set difference problem (Find all members of A that do not also exist in B), you can use the built-in member/2 predicate:
relative_difference( [] , _ , [] ) . % if the source list is exhausted, we're done
relative_difference( [A|As] , Bs , R ) :- % if the source list is non-empty, and
member(A,Bs) , % - the current A is an element of B,
! , % - we insert a deterministic cut (no backtracking)
relative_difference( As , Bs , R ) % - and recurse down, discarding the current A
. %
relative_difference( [A|As] , Bs , [A|R] ) :- % if the source list is non-empty (and A is not an element of B due to the cut inserted earlier)
relative_difference( As , Bs , R ) % we simply add A to the result list and recurse down.
.
One thing you will note here: we are building the result list in all of these examples is built from a variable. The tail of the list is unbound (and passed as the new result to the next recursive call, where it either become a new list node or, at the very end, the empty list.
This has the effect of
building the list in order (rather than in reverse order).
if the result was bound on the initial call, unification against the expected result occurs item by item as the recursion proceeds, which means
execution is short-circuited when the first unification failure occurs.
If your prolog implementation doesn't have member/2 as a built in, it's easy enough to implement. Something like this ought to do it:
member(X,[X|T]) :- ! . % A hit! cut and succeed.
member(X,[_|T]) :- member(X,T) . % ... and a miss. Just recurse down on the tail.