I'm trying to learn Prolog, I'm having trouble defining the predicate:
In Prolog define a predicate substitute (L1, X, L2) which every second element of the list L1 (starting from the second element) replaces with element X.
Examples:
L1 = [a, b, c], X = 1, L2 = [a, 1, c]
L1 = [a, b, c, d], X = a, L2 = [a, a, c, a]
I tried this way:
replace( [], _, [] ) :- ! .
replace( [X|Xs], T, [Z1,Z2|Zs] ):-
Z1 = X ,
Z2 = T ,
replace(Xs,T,Zs).
But it adds items to the second list, not replaces them.
Thank you in advance for your help.
Your problem is that you are pulling items off the list 1 at a time. To replace every other item, you can do it a couple of ways:
Pull items off 2 at a time
Try this to replace the even number list elements (where the 1st element in the list is item number 1.
You have the special case of the empty list:
replace( [] , _ , [] ) .
And the special case of a list of length 1:
replace( [X] , _ , [X] ) .
And then the general case (lists of length > 1):
replace( [X,_|Xs] , R , [X,R|Ys] ) :- replace(Xs, R, Ys).
Putting it all together, we get:
replace( [] , _ , [] ) .
replace( [X] , _ , [X] ) .
replace( [X,_|Xs] , R , [X,R|Ys] ) :- replace(Xs, R, Ys).
Track State As You Go
This isn't much more difficult. And it opens the possibility of
making things more general. To do this we use a helper
predicate. Ultimately, it's not a lot different.
First, our replace/3 is just a wrapper around invoking the
helper predicate, to which we pass two additional bits of state:
the current index value (1), and
the modulus we'll use to determine which elements get replaced
replace( Xs, R, Ys ) :- replace(Xs, R, 1, 2, Ys).
Here's the helper predicated replace/5:
replace( [] , _ , _ , _ , [] ) .
replace( [X|Xs] , R , N , M , [Y|Ys] ) :-
try_swap(X,R,N,M,Y),
N1 is N+1,
replace(Xs, R, N1, M, Ys ).
try_swap( _ , R , N , M , R ) :- 0 is N mod M, !.
try_swap( X , _ , _ , _ , X ) .
And putting it all together:
replace( Xs, R, Ys ) :- replace(Xs, R, 1, 2, Ys).
replace( [] , _ , _ , _ , [] ) .
replace( [X|Xs] , R , N , M , [Y|Ys] ) :-
try_swap(X,R,N,M,Y),
N1 is N+1,
replace(Xs, R, N1, M, Ys ).
try_swap( _ , R , N , M , R ) :- 0 is N mod M, !.
try_swap( X , _ , _ , _ , X ) .
You can write it as two functions that call themselves recursively in turn.
One replacing elements at odd positions, the other replacing elements at even positions:
replace_even([], _, [] ).
replace_even([H|T], R, [H|O]) :-
replace_odd(T, R, O).
replace_odd([], _, []).
replace_odd([_|T], R, [R|O]) :-
replace_even(T, R, O).
Related
count_element(Element, List, Result) :-
count_element(Element, List, 0, Result). % here I start the real rule with counter initialized to 0
count_element(Element, [], Counter, Counter). % if it arrives to the end of the list so there isn't any other element, Result is Counter.
count_element(Element, [Head | Rest], Counter, Result) :- % if Head is Element, Counter increments
Head =:= Element,
NewCounter is Counter+1.
count_element(Element, Rest, NewCounter, Result). % start recurively the function with the list without the head
count_element(Element, [Head | Rest], Counter, Result) :- % if head is not the element, simply start recursively maintaining the counter
Head \= Element,
count_element(Element, Rest, Counter, Result).
I get this:
?- count_element(3,[1,2,3,3],R).
true ;
true ;
true ;
true ;
false.
but no Result of how many occurences of that certain Element...
other interesting results:
?- count_element(3,[3],R).
true ;
true ;
false.
?- count_element(3,[1],R).
true ;
R = 0 ;
true ;
false.
?- count_element(3,[],R).
R = 0 ;
true ;
false.
You have a lot of singletons. That's a code smell that you're doing something
not quite right.
Also, this evaluates the left-hand side and the right-hand side as arithmetic expressions and compares the results:
Head =:= Element
whilst this tests whether or not the left-hand side can be unified with the right-hand side.
The one is not the converse of the other.
Prolog has multiple flavours of "equality".
What you probably want are ==/2 and \==/2 which compare to terms for equivalency, but variables are only equal to themselves. No unification is done (e.g., the variable A is only equivalent to itself, it's not equivalant to the variables _, B, or C, and its not equivalent to a atom, term or number).
Rewriting your example (with slightly shorter variable names), we get:
count_element( E, Ls, R ) :- count_element( E, Ls, 0, R ) .
count_element( _ , [] , C , C ) .
count_element( E , [H|T] , C , R ) :- H == E, C1 is C+1, count_element(E,T,C1,R) .
count_element( E , [H|T] , C , R ) :- H \== E, count_element(E,T,C,R) .
We can simplify this by introducing a cut (!/0), to eliminate the choice point at H == E (the two items, having been found equivalent, are not going to magically become non-equivalent on backtracking).
That gives us this:
count_element( E, Ls, R ) :- count_element( E, Ls, 0, R ) .
count_element( _ , [] , C , C ) .
count_element( E , [H|T] , C , R ) :- H == E, !, C1 is C+1, count_element(E,T,C1,R) .
count_element( E , [H|T] , C , R ) :- count_element(E,T,C,R) .
Alternatively, you could use a soft cut (Condition -> Then ; Else ).
That gives us:
count_element( E, Ls, R ) :- count_element( E, Ls, 0, R ) .
count_element( _ , [] , C , C ) .
count_element( E , [H|T] , C , R ) :-
( H == E -> C1 is C+1, C1 = C ),
count_element(E,T,C1,R)
.
Given two binary trees T1 and T2 having the same height, I would like to know how to check if the number of nodes of T1 is equal to the number of nodes in T2, for each value of depth D.
I wrote a predicate numberOfNodesatD(T, N, D) which calculates the number of nodes at a depth D, but I am not able to define in Prolog the equality between the number of nodes if N1 == N2.
Riffing off my answer to your earlier question, Prolog - Find the depth of an element in a binary tree,
We can use
visit(T,P,D) :- visit(T,0,P,D) .
visit( t(_,L,_) , N, P, D ) :- N1 is N+1, visit(L,N1,P,D) .
visit( t(P,_,_) , D, P, D ) .
visit( t(_,_,R) , N, P, D ) :- N1 is N+1, visit(R,N1,P,D) .
and do something like this:
node_count_by_depth(T,D,N) :-
findall( D, visit(T,_,D), Ds ) ,
msort(Ds,Ss)l ,
groups(Ss,Fs) .
groups( [] , [] ) .
groups( [X|Xs] , Ys ) :- groups(Xs, X:1, Ys ).
groups( [] , Y:N , [Y:N] ) . % the end of the source list is a sequence break.
groups( [X|Xs] , X:N , Ys ) :- % if we haven't hit a sequence break...
N1 is N+1 , % - increment the count
groups(Xs,X:N1,Ys) . % - and recurse down
groups( [X|Xs] , Y:N , [Y:N|Ys] ) :- % otherwise...
X \= Y , % - we have hit a sequence break,
groups(Xs,X:1,Ys) % - recurse down, having moved the tuple to the result list
. % Easy!
And once you have that, then it's a matter of:
same_number_of_nodes_at_depth(T1,T2,D,N) :-
node_count_by_depth(T1,L1),
node_count_by_depth(T2,L2),
member( D:N, L1 ),
member( D:N, L2 ).
I am working with Prolog sample list programs and triying to do some operations on them. However, I am stuck at a point and couldn't find any solution or sample.
I want to write a function which takes two lists of integers and return a float value. The two lists size are equal. The float value is the result of comparison divided by list size.
The function should compare every elemen of first list to every elemen of the second list. A pair (i, j) is that i is the location of element in first list and j is the location of the element in second list. If element i greater than element j, result of comparison is incremented by 1. If element i less than element j, result of comparison decremented by 1. If equal, nothing happen. At the end of the above operation, we return the float value described above.
Example:
retVal([4,5,3], [8,2,1], Result).
should return Result = (-1+1+1-1+1+1-1+1+1) / 3 = 0.33
In object oriented language, it is as simple as printing something on the console. However, I don't have any idea in Prolog. Thank you in advance.
What you describe by words could be this snippet
retVal(L1,L2, Result) :-
findall(S, (member(X1,L1), member(X2,L2), (X1 < X2 -> S = -1 ; S = 1)), L),
sum_list(L, Sum),
length(L1, Len),
Result is Sum / Len.
Alas, the test outcome doesn't match your expectation
?- retVal([4,5,3], [8,2,1], X).
X = 1.
As liori noted in his comment, your manual calculation is incorrect...
I think this should work:
sgn(X, Y, -1) :- X<Y.
sgn(X, Y, 1) :- X>Y.
sgn(X, X, 0).
ssapd(L, R, O) :- ssapd(L, R, R, 0, 0, O).
ssapd([LI | LR], RL, [RPI | RPL], ACC, ACCL, O) :-
sgn(LI, RPI, SGN), !,
ACC1 is ACC + SGN,
ssapd([LI | LR], RL, RPL, ACC1, ACCL, O).
ssapd([_ | LR], RL, [], ACC, ACCL, O) :-
ACCL1 is ACCL + 1,
ssapd(LR, RL, RL, ACC, ACCL1, O).
ssapd([], _, _, ACC, ACCL, Result) :-
Result is ACC / ACCL.
It's a nice implementation with tail recursion done by using two accumulators, O(n²) time complexity and constant memory (except for the size of input). To execute it, try:
ssapd([4,5,3], [8,2,1], Result).
This is a tail-recursive approach:
compare_list( Xs , Ys , Z ) :-
compare_list( Xs, Ys, 0 , 0 , S , L ) ,
Z is float(S)/float(L)
.
compare_list( [] , [] , S , L , S , L ) .
compare_list( [X|Xs] , [Y|Ys] , A , B , S , L ) :-
A1 is A + sign(X-V) ,
B1 is B + 1 ,
compare_list(Xs,Ys,A1,B1,S,L)
.
Another approach, this time "head recursive":
compare_list( Xs , Ys , Z ) :-
compare_list( Xs , Ys , S , L ) ,
Z is float(S)/float(L)
.
compare_list( [] , [] , 0 , 0 ) .
compare_list( [X|Xs] , [Y|Ys] , S , L ) :-
compare_list(Xs,Ys,S1,L1) ,
S is S1 + sign(X-Y) ,
L is L1 + 1
.
The former implementation won't overflow the stack on long lists as it gets optimized away into [effectively] iteration, but requires accumulators; the latter implementation doesn't require accumulators, but will blow the stack if the list(s) are of sufficient length.
I wrote Prolog code for my assignment to drop the nth element of the give list.
I made a predicate called remove/3 which removes an element from the list by its number, and another predicate called drop2/4 which calls the remove/3 predicate by only the numbers who are divisible by N.
But there is a small logical error as it only removes 1 element from the list which is the last element which is divisible by N. I guess this is because when I call the remove/3 predicate with the list L and X it adds all the elements to X then remove element number N, however, L remains the same, so when I call remove/3 again with another N, it doesn't continue on the previous edit, so the previous element which was deleted is restored, so that's why only the last element is deleted.
Query example:
drop([a,b,c,d,e,f,g,h,i,k], 3, X).
Result should be: X = [a,b,d,e,g,h,k]
drop(L, N, X):-
drop2(L, N, X, N).
drop2(_, _, _, 1).
drop2(L, N, X, C):-
N mod C =:= 0,
remove(L, N, X),
Z is C-1,
drop2(L, N, X, Z).
drop2(L, N, X, C):-
Z is C-1,
drop2(L, N, X, Z).
remove([_|T], 1, T).
remove([H|T1], N, [H|T2]):-
N > 1,
Z is N - 1,
remove(T1, Z, T2).
That seems complicated to me. You could just say
drop(Xs,N,Rs) :-
integer(N) ,
N > 0 ,
drop(Xs,1,N,Rs)
.
where your helper predicate drop/4 is
drop( [] , _ , _ , [] ) .
drop( [X|Xs] , P , N , Rs ) :-
( 0 =:= P mod N -> R1 = Rs ; [X|R1] = Rs ) ,
P1 is P+1 ,
drop(Xs,P1,N,R1)
.
or the equivalent
drop( [] , _ , _ , [] ) .
drop( [X|Xs] , P , N , [X|Rs] ) :- 0 =\= P mod N , P1 is P+1 , drop(Xs,P1,N,Rs) .
drop( [_|Xs] , P , N , Rs ) :- 0 =:= P mod N , P1 is P+1 , drop(Xs,P1,N,Rs) .
or even
drop( [] , _ , _ , [] ) .
drop( [_|Xs] , P , P , Rs ) :- P1 is 1 , drop(Xs,P1,N,Rs) .
drop( [X|Xs] , P , N , [X|Rs] ) :- P < N , P1 is P+1 , drop(Xs,P1,N,Rs) .
No need for writing recursive code... simply use append/3, length/2, and same_length/2!
list_nth1_dropped(As,N1,Bs) :-
same_length(As,[_|Bs]),
append(Prefix,[_|Suffix],As),
length([_|Prefix],N1),
append(Prefix,Suffix,Bs).
Here's the query the OP gave:
?- Xs = [a,b,c,d,e,f,g,h,i,k],
list_nth1_dropped(Xs,3,Ys).
Xs = [a,b,c,d,e,f,g,h,i,k],
Ys = [a,b, d,e,f,g,h,i,k]
; false.
How about a more general query?
?- list_nth1_dropped([a,b,c,d,e,f],N,Xs).
N = 1, Xs = [ b,c,d,e,f]
; N = 2, Xs = [a, c,d,e,f]
; N = 3, Xs = [a,b, d,e,f]
; N = 4, Xs = [a,b,c, e,f]
; N = 5, Xs = [a,b,c,d, f]
; N = 6, Xs = [a,b,c,d,e ]
; false.
I'm trying to make intersection of 2 lists (i.e. list C contains those and only those elements, that are in A and B), yet as I understand, I get disjunction of 2 lists + any amount of any elements in C.
Intended to work like:
if X is in C, then it must be both in A and in B. (I believe X should iterate ALL members of C !?)
predicate: d(A,B,C) :- (member(X,D)->member(X,A),member(X,B)).
Can you tell: Are my sentence and predicate not equal or did I make another error?
example:
?- [user].
|: d(A,B,C) :- (member(X,D)->(member(X,A),member(X,B))).
|: % user://1 compiled 0.01 sec, 612 bytes
true.
?- d([a,b],[b,c],C)
| .
C = [b|_G21] .
?- d([a,b],[b,c],[b]).
true .
A O(NlogN) solution with duplicates removed:
% untested
intersection(A, B, O) :-
sort(A, AS),
sort(B, BS),
intersection1(AS, BS, O).
intersection1(A, B, O) :-
( A = [AH|AT],
B = [BH|BT]
-> ( AH == BH
-> O = [AH|OT],
intersection1(AT, BT, OT)
; ( AH #< BH
-> intersection1(AT, B, O)
; intersection1(A, BT, O) ) )
; O = [] ).
I like the solution proposed by #salva, though I'd do a more straightforward sort-and-merge, chucking anything that doesn't match instead:
intersect( As , Bs , Cs ) :-
sort( As , SortedAs ) ,
sort( Bs , SortedBs ) ,
merge( SortedAs , SortedBs , Cs )
.
merge( [] , [] , [] ).
merge( [] , [_|_] , [] ).
merge( [_|_] , [] , [] ).
merge( [C|As] , [C|Bs] , [C|Cs] ) :- merge( As , Bs , Cs ) .
merge( [A|As] , [B|Bs] , Cs ) :- A #< B , merge( As , [B|Bs] , Cs ) .
merge( [A|As] , [B|Bs] , Cs ) :- A #> B , merge( [A|As] , Bs , Cs ) .
your predicate d/3 should be reformulated in constructive terms, since Prolog it's 'a tuple at once' relational language:
d(X,Y,Z) :- findall(E, (member(E,X), memberchk(E,Y)), Z).
that yields
?- d([a,b],[b,c],C).
C = [b].
memberchk/2 it's the deterministic version of member/2, used here to enumerate all X' elements. You could understand better the difference if you replace memberchk with member and try to call d/3 with lists containing duplicates.
findall/3 it's the simpler 'all solutions' list constructor.