SWI-Prolog predicates member and nth1 without unification? - prolog

If I use the predicates member or the nt1 in SWI-Prolog as follows:
?- member(X, [A]).
X = A.
or
nth1(N, [A], X).
N = 1,
A = X.
The interpreter unifies the variable A as X.
Is their some alternative version of this functions which does not use the unification. Means, if I call something like this:
?- _member(X, [A]).
it would give
false
as long as the call is not
?- member(X, [X]).
which would lead to
true
And in the same way
_nth1(N, [A], X).
would give false
but
_nth1(N, [X], X).
would give
N = 1

Seems like you just need to roll your own using ==/2 instead of =/2:
See https://swish.swi-prolog.org/p/DqhYGuEf.pl
is_member_of( X , [Y|_] ) :- X == Y .
is_member_of( X , [_|Ys] ) :- is_member_of(X,Ys) .
is_nth0( N , L , E ) :- is_nth(0,L,E,N) .
is_nth1( N , L , E ) :- is_nth(1,L,E,N) .
is_nth( N , [Y|_] , X , N ) :- X == Y .
is_nth( I , [_|Ys] , X , N ) :- J is I+1, is_nth(J,Ys,X,N) .

Related

Even sum & Odd product of a list, Swi-Prolog [duplicate]

I have a list of numbers, I need to calculate the sum of the even numbers of the list and the product of the odd numbers of the same list. I'm new in Prolog, and my searches so far weren't successful. Can anyone help me solve it ?
l_odd_even([]).
l_odd_even([H|T], Odd, [H|Etail]) :-
H rem 2 =:=0,
split(T, Odd, Etail).
l_odd_even([H|T], [H|Otail], Even) :-
H rem 2 =:=1,
split(T, Otail, Even).
Here is a suggestion for the sum of the even numbers from a list:
even(X) :-
Y is mod(X,2), % using "is" to evaluate to number
Y =:= 0.
odd(X) :- % using even
Y is X + 1,
even(Y).
sum_even(0, []). % empty list has zero sum
sum_even(X, [H|T]) :-
even(H),
sum_even(Y, T),
X is Y+H.
sum_even(X, [H|T]) :-
odd(H),
sum_even(X, T). % ignore the odd numbers
Note: My Prolog has oxidized, so there might be better solutions. :-)
Note: Holy cow! There seems to be no Prolog support for syntax highlighting (see here), so I used Erlang syntax.
Ha, it really works. :-)
Running some queries in GNU Prolog, I get:
| ?- sum_even(X,[]).
X = 0 ?
yes
| ?- sum_even(X,[2]).
X = 2 ?
yes
| ?- sum_even(X,[3]).
X = 0 ?
yes
| ?- sum_even(X,[5,4,3,2,1,0]).
X = 6 ?
yes
The ideas applied here should enable you to come up with the needed product.
Use clpfd!
:- use_module(library(clpfd)).
Building on meta-predicate foldl/4, we only need to define what a single folding step is:
sumprod_(Z,S0,S) :-
M #= Z mod 2,
rem_sumprod_(M,Z,S0,S).
rem_sumprod_(0,Z,S0-P,S-P) :-
S0 + Z #= S.
rem_sumprod_(1,Z,S-P0,S-P) :-
P0 * Z #= P.
Let's fold sumprod_/3 over the list!
l_odd_even(Zs,ProductOfOdds,SumOfEvens) :-
foldl(sumprod_,Zs,0-1,SumOfEvens-ProductOfOdds).
Sample query:
?- l_odd_even([1,2,3,4,5,6,7],Odd,Even).
Odd = 105,
Even = 12.
Alternatively, we can define sumprod_/3 even more concisely by using if_/3 and zeven_t/3:
sumprod_(Z,S0-P0,S-P) :-
if_(zeven_t(Z), (S0+Z #= S, P0=P),
(P0*Z #= P, S0=S)).
untested!
sum_odd_product_even([], S, P, S, P).
sum_odd_product_even([H|T], S0, P0, S, P) :-
S1 is S0 + H,
sum_even_product_odd(T, S1, P0, S, P).
sum_even_product_odd([], S, P, S, P).
sum_even_product_odd([H|T], S0, P0, S, P) :-
P1 is P0 * H,
sum_odd_product_even(T, S0, P1, S, P).
sum_odd_product_even(L, S, P) :-
sum_odd_product_even(L, 0, 1, S, P).
sum_even_product_odd(L, S, P) :-
sum_even_product_odd(L, 0, 1, S, P).
It shouldn't get much simpler than
%
% invoke the worker predicate with the accumulators seeded appropriately.
%
odds_and_evens( [O] , P , S ) :- odds_and_evens( [] , O , 0 , P , S ) .
odds_and_evens( [O,E|Ns] , P , S ) :- odds_and_evens( Ns , O , E , P , S ) .
odds_and_evens( [] , P , S , P , S ) . % if the list is exhausted, we're done.
odds_and_evens( [O] , X , X , P , S ) :- % if it's a single element list, we've only an odd element...
P is X*O , % - compute it's product
. % - and we're done.
odds_and_evens( [O,E|Ns] , X , Y , P , S ) :- % if the list is at least two elements in length'e both an odd and an even:
X1 is X*O , % - increment the odd accumulator
Y1 is Y+E , % - increment the even accumulator
odds_and_evens( Ns , X1 , Y1 , P , S ) % - recurse down (until it coalesces into one of the two special cases)
. % Easy!

Definite Logic Program

The aim is to implement the predicate noDupl/2.
The first argument of this predicate is the list to analyze and second argument is the list of numbers which are no duplicate.
I could not understand code below and when I compiled it, it gave an error message that contained is undefined procedure, however as a hint it is written that we can use as predefined predicate contained and notContained. I think I need to define contained and notContained.
noDupl(XS, Res):-
help( XS, [],Res).
help([],_,[]).
help([X|XS],Seen,[X|Res]):-
notContained(X,XS),
notContained(X,Seen),
help(XS, [X|Seen], Res).
help([X|XS],Seen,Res):-
contained(X,Seen),
help(XS, Seen, Res).
help([X|XS],Seen,Res):-
contained(X,XS),
help(XS, [X|Seen], Res).
Could someone please explain me the problem.
The missing definitions might be:
contained(X,[X|_]).
contained(X,[E|Es]) :-
dif(X, E),
contained(X, Es).
notContained(_X, []).
notContained(X, [E|Es]) :-
dif(X, E),
notContained(X, Es).
(I like to call these relations rather memberd/2 and non_member/2.)
The definition you gave extends the relation with an extra argument for the elements considered so far.
To understand the meaning of each clause, read each right-to-left in the direction of the arrow (the :- is a 1970's ASCII-fication of ←). Let's take the first rule:
Provided, that X is not an element of XS, and
provided, that X is not an element of Seen, and
provided, that help(X, [X|Seen], Res) is true,
then also help([X|XS],Seen,[X|Res]) is true.
In other words, if X is neither in the list of visited elements Seen nor in the elements yet to be visited XS, then it does not possess a duplicate.
What is a bit difficult to understand is whether or not the clauses you gave are mutually exclusive - this is, strictly speaking, not your concern, as long as you are only interested in declarative properties, but it is a good idea to avoid such redundancies.
Here is a case, where such redundancy shows:
?- noDupl([a,a,a],U).
U = []
; U = []
; false.
Ideally, the system would give one determinate answer:
?- noDupl([a,a,a], U).
U = [].
Personally, I do not like a lot to split things into too many cases. Essentially, we could have two: it is a duplicate, and it is none.
It is possible to provide a definition that is correct and still fully determinate for the cases where determinism is possible - such as when the first argument is "sufficiently instantiated" (which includes a ground list). Let's see if there are some answers into that direction.
I've annotated your code for you:
noDupl( XS , Res ) :- % Res is the [unique] set of element from the bag XS
help( XS, [],Res) % if invoking the helper succeeds.
. %
help( [] , _ , [] ) . % the empty list is unique.
help( [X|XS] , Seen , [X|Res] ) :- % A non-empty list is unique, if...
notContained(X,XS), % - its head (X) is not contained in its tail (XS), and
notContained(X,Seen), % - X has not already been seen, and
help(XS, [X|Seen], Res). % - the remainder of the list is unique.
help( [X|XS] , Seen , Res ) :- % otherwise...
contained(X,Seen) , % - if X has been seen,
help(XS, Seen, Res). % - we discard it and recurse down on the tail.
help([X|XS],Seen,Res):- % otherwise...
contained(X,XS), % - if X is in the tail of the source list,
help(XS, [X|Seen], Res). % - we discard it (but add it to 'seen').
Your contained/2 and notContained/2` predicates might be defined as this:
contained( X , [X|_] ) :- ! .
contained( X , [Y|Ys] ) :- X \= Y , contained( X , Ys ) .
not_contained( _ , [] ) .
not_contained( X , [Y|Ys] ) :- X \= Y , not_contained(X,Ys) .
Now, I may be missing something in your code, but there's an awful lot of redundancy in it. You could simply write something like this (using the built-ins member/2 and reverse/2):
no_dupes( List , Unique ) :- no_dupes( Bag , [] , Set ) .
no_dupes( [] , V , S ) . % if we've exhausted the bag, the list of visited items is our set (in reverse order of the source)
reverse(V,S) % - reverset it
. % - to put our set in source order
no_dupes( [X|Xs] , V , S ) :- % otherwise ...
( member(X,V) -> % - if X is already in the set,
V1 = V % - then we discard X
; V1 = [X|V] % - else we add X to the set
) , % And...
no_dupes( Xs , V1 , S ) % we recurse down on the remainder
. % Easy!
Can this be done in a pure and efficient way?
Yes, by using
tpartition/4 and (=)/3 like so:
dups_gone([] ,[]).
dups_gone([X|Xs],Zs0) :-
tpartition(=(X),Xs,Ts,Fs),
if_(Ts=[], Zs0=[X|Zs], Zs0=Zs),
dups_gone(Fs,Zs).
Some sample ground queries (all of which succeed deterministically):
?- dups_gone([a,a,a],Xs).
Xs = [].
?- dups_gone([a,b,c],Xs).
Xs = [a, b, c].
?- dups_gone([a,b,c,b],Xs).
Xs = [a, c].
?- dups_gone([a,b,c,b,a],Xs).
Xs = [c].
?- dups_gone([a,b,c,b,a,a,a],Xs).
Xs = [c].
?- dups_gone([a,b,c,b,a,a,a,c],Xs).
Xs = [].
This also works with more general queries. Consider:
?- length(Xs,N), dups_gone(Xs,Zs).
N = 0, Xs = [], Zs = []
; N = 1, Xs = [_A], Zs = [_A]
; N = 2, Xs = [_A,_A], Zs = []
; N = 2, Xs = [_A,_B], Zs = [_A,_B], dif(_A,_B)
; N = 3, Xs = [_A,_A,_A], Zs = []
; N = 3, Xs = [_A,_A,_B], Zs = [_B], dif(_A,_B)
; N = 3, Xs = [_A,_B,_A], Zs = [_B], dif(_A,_B)
; N = 3, Xs = [_B,_A,_A], Zs = [_B], dif(_A,_B), dif(_A,_B)
; N = 3, Xs = [_A,_B,_C], Zs = [_A,_B,_C], dif(_A,_B), dif(_A,_C), dif(_B,_C)
; N = 4, Xs = [_A,_A,_A,_A], Zs = []
...

Predicate that pick elements which are on list twice not less not more

I'm trying to write a predicate twice(El,L) which will return true. when El is on list exactly twice. Here is what I have:
twice(El,L) :- select(El,L,L1), member(El,L1), \+ twice(El,L1).
It works nice for twice(2,[1,2,2,3,4])
but for twice(X,[1,1,2,2,3,3]) it doubles every number X = 1 ; X = 1 ; X = 2... How could I avoid this without using any accumulator?
You want to describe a sequence of elements. For such, there is a special formalism in Prolog called Definite Clause Grammars. Before using the formalism, let's try to figure out how a sequence with E occurring exactly twice looks like:
First, is a possibly empty sequence which does not contain E
then, there is one occurrence of E
then again a possibly empty sequence without E
then, there is the second occurrence of E
then again a possibly empty sequence without E.
Now, to put this into the DCG formalism
twice(E, L) :-
phrase(twice_occurring(E), L). % Interface
twice_occurring(E) -->
seq_without(E), % 1.
[E], % 2.
seq_without(E), % 3.
[E], % 4.
seq_without(E). % 5.
seq_without(_E) -->
[].
seq_without(E) -->
[X],
{dif(X,E)},
seq_without(E).
Or, more compactly by using all//1 and avoiding auxiliary definitions:
twice(E, L) :-
phrase(( all(dif(E)), [E], all(dif(E)), [E], all(dif(E)) ), L).
There is essentially only one drawback with these definitions: On current systems, they are not optimally implemented. See this if you want to know more.
Stay both logically pure and efficient by using if_/3 and
(=)/3 by #false. It goes like this:
list_member1x([X|Xs],E) :-
if_(X=E, maplist(dif(E),Xs), list_member1x(Xs,E)).
list_member2x([X|Xs],E) :-
if_(X=E, list_member1x(Xs,E), list_member2x(Xs,E)).
twice(E,Xs) :-
list_member2x(Xs,E).
That's it. Let's run some queries!
?- twice(E,[1,2,3,4,5,2,3,4]).
E = 2 ;
E = 3 ;
E = 4 ;
false.
Now something a little more general:
?- twice(X,[A,B,C,D]).
A=X , B=X , dif(C,X), dif(D,X) ;
A=X , dif(B,X), C=X , dif(D,X) ;
A=X , dif(B,X), dif(C,X), D=X ;
dif(A,X), B=X , C=X , dif(D,X) ;
dif(A,X), B=X , dif(C,X), D=X ;
dif(A,X), dif(B,X), C=X , D=X ;
false.
Here are the queries the OP gave:
?- twice(2,[1,2,2,3,4]).
true.
?- twice(E,[1,1,2,2,3,3]).
E = 1 ;
E = 2 ;
E = 3 ;
false.
Edit
As an alternative, use meta-predicate tcount/3 in combination with (=)/3 like this:
twice(E,Xs) :- tcount(=(E),Xs,2).
Try:
twice(E,L) :-
append(B1,[E|A1],L),
\+ member(E,B1),
append(B2,[E|A2],A1),
\+ member(E,B2),
\+ member(E,A2).
Addendum
In case that the list of number could be (partially) unbound, following variant solves the issues. It uses "dif" instead of "\=", "+". In addition, it is a few optimized ("append" and "member" have been joined to a single "appendchk"):
appendchk(L,L).
appendchk([E|Q2],[H|R]) :-
dif(H,E),
appendchk([E|Q2],R).
notmember(_,[]).
notmember(X,[H|Q]) :-
dif(X,H),
notmember(X,Q).
twice(E,L) :-
appendchk([E|A1],L),
appendchk([E|A2],A1),
notmember(E,A2).
Examples:
twice(1,[1,2,3,4,2,3,2]).
false
twice(2,[1,2,3,4,2,3,2]).
false
twice(3,[1,2,3,4,2,3,2]).
true
twice(X,[1,2,3,4,2,3,2]).
X = 3
false
twice(X,[A,B]).
A = B, B = X
twice(X,[A,B,C]).
A = B, B = X,
dif(X, C)
A = C, C = X,
dif(B, X)
B = C, C = X,
dif(A, X)
Here is how we can declare, courtesy library(aggregate), the required constraint:
twice(El, L) :-
aggregate(count, P^nth1(P,L,El), 2).
Where list' elements are restricted to integers, library(clpfd) reification hint hosts another solution:
twice(El, L) :- vs_n_num(L,El,2).
% aggregate(count, P^nth1(P,L,El), 2).

Division two naturals in prolog [duplicate]

This question already has answers here:
Dividing two integers with an alternative way
(3 answers)
Closed 7 years ago.
I have written the following code:
nat(0).
nat(s(X)) :- nat(X).
divide(0,_,0).
divide(X,Y,D) :- X#<Y, D is 0.
divide(X,s(0),X).
divide(_,0,undefined) :- !.
Everything is right up to here. but what should i write, to calculate the division of two other naturals? for example
divide(s(s(s(s(s(s(s(s(0)))))))),s(s(0)),D).???
I think the easiest way would be to define subtraction and then apply it recursively with a counter. I'm not able to run this right now but I assume it'd look something like this:
nat(0).
nat(s(X)) :- nat(X).
divide(_,0,_):- !, fail.
divide(X,Y,R):-
iter_subtract(X,Y,0,R).
iter_subtract(X,Y,N,N):- X#<Y, !.
iter_subtract(X,Y,C,R):-
subtract(X,Y,N),
D = s(C),
iter_subtract(N,Y,D,R).
subtract(A,0,A):-!.
subtract(s(X),s(B),R):-
subtract(X,B,R).
you can easily divide two numbers as following:
mydiv(0,_,0).
mydiv(_,0,undefined):- !.
mydiv(X,Y,D) :- X >= Y , Z is X - Y , mydiv(Z,Y,M) , D is M + 1 .
output:
?- mydiv(10,4,Q). false.
?- mydiv(100,2,Q). Q = 50 .
to run with debug info:
mydiv(0,_,0) :- write('mydiv(0,_,0)\n').
mydiv(_,0,undefined):- write('mydiv(_,0,undefined)\n'),!.
mydiv(X,Y,D) :- write('mydiv('),write(X) , write(','), write(Y) , write(',') , write(D) , write(')') , nl,
X >= Y , Z is X - Y , mydiv(Z,Y,M) , D is M + 1 .
output:
?- mydiv(20,2,Q). mydiv(20,2,_G3941) mydiv(18,2,_L1420)
mydiv(16,2,_L1435) mydiv(14,2,_L1450) mydiv(12,2,_L1465)
mydiv(10,2,_L1480) mydiv(8,2,_L1495) mydiv(6,2,_L1510)
mydiv(4,2,_L1525) mydiv(2,2,_L1540) mydiv(0,__,0) Q = 10 .
with natural function:
natural(0).
natural(X) :- X < 0 , !, fail.
natural(X) :- Y is X - 1 , natural(Y).
mydiv(0,_,0) :- write('mydiv(0,_,0)\n').
mydiv(_,0,undefined):- write('mydiv(_,0,undefined)\n'),!.
mydiv(X,Y,D) :- write('mydiv('),write(X) , write(','), write(Y) , write(',') , write(D) , write(')') , nl,
natural(X), natural(Y), X >= Y , Z is X - Y , mydiv(Z,Y,M) , D is M + 1 .

Write a recursive Prolog predicate of three arguments, called common, which returns the number of elements that belong to both lists

Write a recursive Prolog predicate of three arguments, called common, which returns the number of elements that belong to both lists.
For example:
?- common ( [a, b, c, k, h], [b,c,d,e], N).
N=2.
?- common ( [b, a, c, d], [a, b, c, d, e] , N).
N=4.
Preserve logical-purity!
:- use_module(library(clpfd)).
First, we define meta-predicate tcountd/3 in order to discount duplicate list items. tcount/3 is similar to tcount/3, but uses tfilter/3 and dif/3 for excluding duplicates:
:- meta_predicate tcountd(2,?,?).
tcountd(P_2,List,Count) :-
list_tcountd_pred(List,Count,P_2).
:- meta_predicate list_tcountd_pred(?,?,2).
list_tcountd_pred([] ,0, _ ).
list_tcountd_pred([X|Xs0],N,P_2) :-
if_(call(P_2,X), (N #= N0+1, N0 #>= 0), N = N0),
tfilter(dif(X),Xs0,Xs),
list_tcountd_pred(Xs,N0,P_2).
We define common/3 based upon meta-predicate tcountd/3, Prolog lambdas, and memberd_t/3:
common(Xs,Ys,N) :-
tcountd(Ys+\X^memberd_t(X,Ys),Xs,N).
Let's run the sample queries the OP gave:
?- common([a,b,c,k,h],[b,c,d,e],N).
N = 2.
?- common([b,a,c,d],[a,b,c,d,e],N).
N = 4.
As common/3 is monotone, we get sound answers with non-ground queries, too! Consider:
?- common([A,B],[X,Y],N).
N = 1, A=B , B=X
; N = 2, A=X , B=Y , dif(X,Y)
; N = 1, A=X , dif(B,X), dif(B,Y)
; N = 1, A=B , B=Y , dif(X,Y)
; N = 2, A=Y , B=X , dif(X,Y)
; N = 1, A=Y , dif(B,X), dif(B,Y), dif(X,Y)
; N = 0, A=B , dif(B,X), dif(B,Y)
; N = 1, dif(A,X), dif(A,Y), B=X
; N = 1, dif(A,X), dif(A,Y), B=Y , dif(X,Y)
; N = 0, dif(A,B), dif(A,X), dif(A,Y), dif(B,X), dif(B,Y).
Trivially to do using intersection/3 built-in:
common(A, B, N) :-
intersection(A, B, C),
length(C, N).
Test run:
?- common([a, b, c, k, h], [b,c,d,e], N).
N = 2.
?- common([b, a, c, d], [a, b, c, d, e], N).
N = 4.
Notice that there is no space between "common" and "(" in the queries. This is important. Queries as you stated in the question (with space between "common" and "(") will give syntax error.
This is one way, assuming you want to ensure that the result is a set (unique items) rather than a bag (allows duplicate items) :
set_intersection( Xs, Ys, Zs ) :- % to compute the set intersection,
sort(Xs,X1) , % - sort the 1st set, removing duplicates (so that it's a *set* rather than a *bag* ) ,
sort(Ys,Y1) , % - sort the 2nd set, removing duplicates (so that it's a *set* rather than a *bag* ) ,
common( Xs , Ys , Zs ) % - merge the two now-ordered sets, keeping only the common items
.
common( Xs , Ys , [] ) :-
( Xs=[] ; Ys=[] ) ,
! .
common( [X|Xs] , [X|Ys] , [X|Zs] ) :-
common( Xs , Ys , Zs ) .
Another, simpler way:
set_intersection( Xs , Ys , Zs ) :-
set_of(Z,(member(Z,Xs),member(Z,Ys)),Zs)
.
Another way:
set_intersection( Xs , Ys , Zs ) :- % compute the set intersection by
set_intersectin( Xs , Ys , [] , Zs ) . % invoking the worker predicate
set_intersection( [] , _ , Zs , Zs ) . % when we run out of Xs, we're done.
set_intersection( [X|Xs] , Ys , Ts , Zs ) :- % otherwise,
member(X,Ys) , % if X is a member of Ys,
\+ member(X,Ts) , % and we don't yet have an X,
set_intersection( Xs , Ys , [X|Ts] , Zs ) % add X to the accumulator and recurse down
. %

Resources