Tried before, but it is still kind of a mess for me. Thought it was longest subsequence, but it actually isn't. So writing it with better examples. I am trying to write a Prolog predicate to compare two strings to see if they have the same elements and to print them out (only once per member). Currently I have written this to get the strings into 2 different lists for easier checking:
However, I am having trouble finding the right way to compare EVERY element in those two lists no matter where they are. I have found ways to compare till it founds one and it returns true, but I need it to compare every element in both lists and output them. I know it has to do with heads and comparing them, then adding the next first list member as the new head etc. But I can't figure out a way to do it. Also, intersection kinda does what I need, but it gives me every element (even mutliple times). I need it to stop after it finds the matching element so it finds them all only once.
plates(X,Y,Mem,Num):-
atom_chars(X,Xs),
atom_chars(Y,Ys),
compare_list(Xs,Ys,Mem),
length(Mem,Num).
compare_list([], _, []).
compare_list([H1|T1], L, R) :-
(check_element(H1, L)
->R = [H1|R]
;R = R
),
compare_list(T1, L, R).
check_element(_, []).
check_element(X, [H|T]) :-
X = H,
check_element(X, T).
Example1:
?-plates('111AXB','112XXX', Mem, Num).
Should output:
Mem = ['1','1','X'],
Num = 3.
Example2:
?-plates('456XYZ','678ABC', Mem, Num).
Should output:
Mem = ['6'],
Num = 1.
I tried implementing the solution here:
PROLOG Comparing 2 lists
My test:
?- plates('ABC123','123ABC',Mem,Num).
My output:
Mem = [],
Num = 0.
Expected:
Mem = ['A', 'B', 'C', '1', '2', '3'],
Num = 6.
But I couldn't get it to work the way I wanted it to...
Any help would be very appreciated!
You could write something like:
plates(X,Y,Mem,Num):-
atom_chars(X,Xs),
atom_chars(Y,Ys),
inter(Xs,Ys,Mem),
length(Mem,Num),!.
inter(_,[],[]).
inter([],_,[]).
inter([H|T],L,[H|T1]):-
member(H,L),
delete(H,L,L1),
inter(T,L1,T1).
inter([H|T],L,List):- \+member(H,L),inter(T,L,List).
delete(H,[H|T],T).
delete(H,[X|T1],[X|T]):-dif(H,X),delete(H,T1,T).
Where inter finds the intersection and by checking if an element of first list occurs in second and then adds it to third list and deletes it from the second.Some examples:
?- plates('112XXX','111AXB', Mem, Num).
Mem = ['1', '1', 'X'],
Num = 3.
?- plates('111AXB','112XXX', Mem, Num).
Mem = ['1', '1', 'X'],
Num = 3.
?- plates('456XYZ','678ABC', Mem, Num).
Mem = ['6'],
Num = 1.
?- plates('ABC123','123ABC',Mem,Num).
Mem = ['A', 'B', 'C', '1', '2', '3'],
Num = 6.
?- plates('123ABC','345DEF',Mem,Num).
Mem = ['3'],
Num = 1.
Related
I need to multiply and sum one list, the output should be like this:
?- tp4([1,7,0,1,2,3,5], L).
L = [210,19,1,7,0,1,2,3,5]
First the multi, next the sum and at the end the rest of the numbers.
Here is a builing brick answer to your question since you seem to have a "where to start" problem. It is important to learn it by yourself, therefore you can conclude the correct answer by using maplist/2 and fold/4 as mentioned from David Tonhofer. But these are "advanced" predicates, so lets start from scratch and implement the base functionalities.
First: how to append elements to a list. You can either put something as a head of a list ([Head|List]) or use the predicate append/2 (which is build in but you can easily implement it by yourself). Note that variables start with a capital letter.
?- List=[1,2,3,4], Head = 0, Out=[Head|List].
Head = 0,
List = [1, 2, 3, 4],
Out = [0, 1, 2, 3, 4].
?- List2=[1,2,3,4], List1 = [0], append(List1,List2,Out).
List1 = [0],
List2 = [1, 2, 3, 4],
Out = [0, 1, 2, 3, 4].
You are be able to add elements to a list.
If you want to implement your own predicate, which works on lists, you either use the inbuild predicates or implement it yourself. We'll do the second one for the example of subtraction (all elements are subtracted from the last element).
Our predicate subtract/2 needs 2 attributes: a list (input) and a "return" value (output).
If the list has only one element ([H]), return the element. Otherwise split the list into a Head element and a Rest list ([Head|Rest]), compute the substract value for the list Rest (Tmp) and subtract Head from it:
subtract([H],[H]).
subtract([Head|Rest], Sub):-
subtract(Rest,Tmp),
Sub is Tmp - Head.
Test:
?- subtract([1,2,3,10],O).
O = 4 ;
false.
Works, not perfect but works. Now you know how to add elements to a list and have an example how to build predicated which operate on lists and use arithemtic functions. Now you can build your desired function.
You need to walk the list and compute the product and sum as you go from element to element. Given the neutral elements of the product and sum are, respectively, 1 and 0:
product_sum_list([Head| Tail], [Product, Sum, Head| Tail]) :-
product_sum_list(Tail, Head, 1, Product, 0, Sum).
Note that we're requiring the list to have at least one element. The auxiliary product_sum_list/6 performs the actual computation of the product and sum:
product_sum_list([], Last, Product0, Product, Sum0, Sum) :-
Product is Product0 * Last,
Sum is Sum0 + Last.
product_sum_list([Next| Tail], Current, Product0, Product, Sum0, Sum) :-
Product1 is Product0 * Current,
Sum1 is Sum0 + Current,
product_sum_list(Tail, Next, Product1, Product, Sum1, Sum).
By splitting the list between its head tail moving the tail to the first argument of the auxiliary predicate, we take advantage of the first argument indexing provided by the generality of Prolog systems to avoid the creation of spurious choice-points.
Sample call:
| ?- product_sum_list([1,7,0,1,2,3,5], L).
L = [0,19,1,7,0,1,2,3,5]
yes
You can achieve the same results using, as David suggested, meta-predicates for mapping and folding lists. But given that we need to compute both product and sum, the straight-forward solution is simpler and more efficient.
A common Prolog idiom is the use of a helper predicate, that takes extra arguments that maintain state. These also help you get to tail recursion so as to not consume stack.
The naive way to multiply a list might be:
multiply( [] , 0 ) . % The empty list has a product of zero.
multiply( [P] , P ) . % A list of length 1 is the value of the singleton element.
multiply( [N|Ns] , P ) :- % To compute the product of a list of length > 1...
multiply(Ns,T), % - recursively multiply the tail of the list, then
P is N * T % - multiply the head by the product of the tail
. % Easy!
Summation would be pretty much identical save for the operation involved.
[Note: given a list of sufficient length, this would eventually fail due to a stack overflow.]
Using a helper predicate (1) makes it tail recursive, meaning it won't blow up and die on a long list, and (2) will facilitate combining summation and multiplication. The 'helper' implementation looks like this:
multiply( [] , 0 ) .
multiply( [N|Ns] , P ) :- multiply(Ns,N,P).
multiply( [] , P , P ) .
multiply( [N|Ns] , T , P ) :-
T1 is T * N ,
multiply( Ns, T1, P )
.
And summation, again, is pretty much identical.
Now we can combine them to get what you want:
multiply_and_sum( [] , [0,0] ) .
multiply_and_sum( [N|Ns] , [P,S|Ns] ) :-
multiply_and_sum( Ns, N, N, P, S )
.
multiply_and_sum( [] , P, S, P, S ) .
multiply_and_sum( [N|Ns] , X, Y, P, S ) :-
X1 is X * N,
Y1 is Y + N,
multiply_and_sum( Ns, X1, Y1, P , S )
.
I am new in prolog programming and I trying to experiment with it
I have 2 questions
suppose I have some facts
fact('A', 'B').
fact('A', 'C').
fact('A', 'D').
when I write fact('A', X), the X will be of 3 values 'B', 'C', and 'D'
how do I write a rule to get how many times 'A' has a pair, in this case the answer will be 3
suppose I have a fact
a([1,2,4,5]).
how do I write a rule to loop through the elements to add them, i.e. find the sigma
thank you
If you just need to count solutions and you are using SWI-Prolog, use aggregate_all:
?- aggregate_all(count, fact('A', _), N).
This way you don't need to existentially qualify variables, you can just "skip" it from the query by using an anonymous variable in its place.
This also correctly counts 0 solutions without further code tricks:
?- aggregate_all(count, fail, N).
To sum a list, you can use sum_list/2 from library(lists). Note that you could also use library(aggregate) for this, if you have a backtrackable predicate (a table of facts) instead of a list. This is also the more usual way to represent a "list" of things in the database.
a(1).
a(2).
a(4).
a(5).
This is how you'd usually find the sum of all rows in your table:
?- aggregate_all(sum(X), a(X), Sum).
Sum = 12.
You can have more columns in your table, of course.
p(a, 3).
p(b, 2).
p(b, 1).
p(a, 2).
p(a, 0).
You can sum those like this:
?- aggregate_all(sum(X), p(a, X), Sum).
Sum = 5.
?- aggregate_all(sum(X), p(b, X), Sum).
Sum = 3.
?- aggregate_all(sum(X), p(foo, X), Sum).
Sum = 0.
?- aggregate_all(sum(X), p(_, X), Sum). % total sum
Sum = 8.
In contrast, you can use aggreagate to get the different groups:
?- aggregate(sum(X), p(A, X), Sum).
A = a,
Sum = 5 ;
A = b,
Sum = 3.
You can collect a list of solutions and get the list's size:
?- findall(X, fact('A',X), List), length(List,Count).
List = ['B', 'C', 'D'],
Count = 3.
or better use the aggregation predicates from library(aggregate):
?- aggregate(count, X^fact('A',X), Count).
Count = 3.
Note caret-notation X^ to signify that X is not a variable over which aggregate(count, Goal_with_X, Count). should backtrack (giving three times a count of 1) but a free variable of the Goal_with_X which varies over the bag of solutions whose size shall be assessed.
I am new to prolog and I don't really know how to solve this problem. I have a list which contains 7 numbers , I was able to get the Max and the Min of these numbers , but after that I have to write out an element from an another list with the same index of min and max of the first list .
start :- writeln('Write in seven numbers then type end.'),
fill(L),
lght(L,Sm),
write(Sm),
writeln(L),
avg(L,Arvg),
writeln('Avg of list:'),
write(Arvg),
min(L,Min),write('a minimum:'),write(Min),
max(L,Max),write('a maximum:'),write(Max)
ffile(F).
min([F|T],Min):-min(T,Min,F).
min([F|T],Min,Act):- number(F),F < Act, Newact is F, min(T,Min,Newact).
min([_|T],Min,Act):- min(T,Min,Act).
min([],Min,Min).
max([F|T],Max):-max(T,Max,F).
max([F|T],Max,Act):- number(F),F > Act, Newact is F, max(T,Max,Newact).
max([_|T],Max,Act):- max(T,Max,Act).
max([],Max,Max).
So I don't really have a clue how to match the min and max to a day for example from an another list.
P.S My code may contains non english words because I did not write it it full english.
One step to answer your question will be to modify your predicates that find the minimum and maximum of a list by returning also the index. For example, modifying your code as:
minimum([Head| Tail], Minimum, Index) :-
minimum(Tail, Head, Minimum, 2, 1, Index).
minimum([], Minimum, Minimum, _, Index, Index).
minimum([Head| Tail], Minimum0, Minimum, Position, Index0, Index) :-
NextPosition is Position + 1,
( Head #< Minimum0 ->
minimum(Tail, Head, Minimum, NextPosition, Position, Index)
; minimum(Tail, Minimum0, Minimum, NextPosition, Index0, Index)
).
I used term comparison instead of arithmetic comparison to make the predicate more general. Sample calls:
| ?- minimum([7,3,4,5,1], M, I).
M = 1, I = 5
yes
| ?- minimum([7,3,1,4,5], M, I).
M = 1, I = 3
yes
| ?- minimum([1,7,3,4,5], M, I).
M = I, I = 1
yes
Can you proceed from here and update your answer with your efforts?
You could take the following approach:
make a list key-value pairs where the original value is the key and the index is the value;
sort by the key (the original value);
the first and the last values are now the indices of the min and the max, respectively;
use the two indices and nth1/3 to get the elements you need from the other list.
But do you really need the indices? If you only thought you need them because you'd like to get the elements from the other list, consider, instead:
make a list of key-value pairs where the key is the elements from the first list and the value is the corresponding element from the second list;
sort by key, get the first and the last value.
Like this:
keys_vals_min_max(Keys, Values, Min, Max) :-
pairs_keys_values(Pairs, Keys, Values),
keysort(Pairs, [_-Min|Rest]),
last(Rest, _-Max).
With this I get:
?- keys_vals_min_max([2,7,1,3,5,4,6], [a,b,c,d,e,f,g], Min, Max).
Min = c,
Max = b.
Easy, right?
(Note: keysort/2 does not remove duplicates and is stable.)
Please don't do this crap where you force the user to enter numbers one by one. This is ridiculous. If you need a list of 7 numbers, just type: [1,2,3,4,5,6,7]. If you need the average of the numbers in a list, define a predicate called list_average/2 and let the user query it like this:
?- list_average([1,2,3,4], Average).
Average = 2.5.
If you think you need state, don't worry too much about it. On the top level, you can start by writing down your input, then just hit the "up" button to get the previous query, and keep on adding stuff at the end of it. For example:
?- L = [1,2,3].
L = [1, 2, 3].
?- L = [1,2,3], length(L, N).
L = [1, 2, 3],
N = 3.
?- L = [1,2,3], length(L, N), sumlist(L, Sum).
L = [1, 2, 3],
N = 3,
Sum = 6.
?- L = [1,2,3], length(L, N), sumlist(L, Sum), Average is Sum / N.
L = [1, 2, 3],
N = 3,
Sum = 6,
Average = 2.
What if you want different input? Just hit the "up" button yet again and change the L:
?- L = [1,42], length(L, N), sumlist(L, Sum), Average is Sum / N.
L = [1, 42],
N = 2,
Sum = 43,
Average = 21.5.
Thank you for your answers!
I was able to finish my task by writing a code that searches for the Index of the Min and Max in the first list and then matching the index numbers with the other list .
index([Element|_], Element, 0).
index([_|Tail], Element, Index):-
index(Tail, Element, Index1),
Index is Index1+1.
I used this code for searching for the indexes
match([Elem|_],Num,Num,Elem) :-
!.
match([_|Tail],Num,Count,MatchedNumber) :-
Count < Num,
Count1 is Count+1,
match(Tail,Num,Count1,MatchedNumber).
And then this code to match the index number with the other List's
I have defined a code in PROLOG :
is_member(X, [X|_]).
is_member(X, [_|T]) :-
is_member(X, T).
I am confused by these two outputs :
out1:
is_member('a', ['b', 'c', 'd', 'a']).
>> True.
out2:
Chars = ['b', 'c', 'd', 'a'].
is_member('a', Chars).
>> Chars = [a|_2356]
Can someone help me out here? I though that output should be True.. I am trying to understand the logic here, but obviously I am lost.
Thank you for any help or advice in advance.
Here's how Prolog queries basically work.
First of all, a complete query ends with a period (.). When you execute:
Chars = [a, b, c, d].
This is a complete query since it ends in a period. When you execute a query, Prolog attempts to make it succeed via some binding of the given variables. If it is able to do so, it will simply display the variable bindings that result in success. In this particular case, the solution is trivial: Chars is bound to [a, b, c, d].
Suppose you enter the above and then you follow this with:
is_member(a, Chars).
Since the previous query completed (it ended in a period), Prolog sees this Chars as a new variable. It is no longer bound to [a, b, c, d] because the previous query ended. Prolog looks at this query and determines what binding(s) for Chars will cause it to succeed. The result is:
Chars = [a|_2356]
Prolog is telling you that a valid solution is obtained by binding Chars to the list [a|_2356] which is any list that has a as its first element. What you didn't show is that Prolog prompts for additional solutions. If you press ;, it shows you more solutions to the is_member(a, Chars). query:
3 ?- is_member(a, Chars).
Chars = [a|_5034] ;
Chars = [_5032, a|_5040] ;
Chars = [_5032, _5038, a|_5046] ;
...
In other words, is_member(a, Chars) has an infinite number of solutions. They are lists that have a as the first element, a as the second, etc.
In Prolog, if you want to establish a series of conditions that must all be true in sequence, you use a comma, not a period, to separate each condition, then end the whole thing in a period:
4 ?- Chars = [a,b,c,d], is_member(a, Chars).
Chars = [a, b, c, d] ;
false.
This query says you want to bind Chars to [a, b, c, d] and determine if a is a member of Chars. Prolog is then saying that it succeeded with one solution, Chars = [a,b,c,d]. Entering ; seeks more solutions, which comes back false since there are no additional solutions.
Let's try Isabella's other example with x:
5 ?- Chars = [a,b,c,d], is_member(x, Chars).
false.
In this case, Prolog could not find a solution, so it simply fails (showing false).
I am trying to understand the unique predicate:
for example:
unique([H|T],[H|TU]) :- delete(T,E,TN), unique(TN,TU).
delete(T,E,TN) is true if a list TN is identical to a list T
after removing all occurrences of an element E.
delete([H|T],H,TN) :- delete(T,H,TN).
delete([H|T],E,[H|TN]) :- \+ H=E, delete(T,E,TN).
delete([],_,[]).
unique(['a','b','a','c'],X).
X = [a, b, c] <- Enter was pressed
Yes
So it comparing two lists
T = ['a', 'b', 'd', 'f', 't']
TN =['a', 'b', 'd']
removes the occurrences of common elements
This is the entire code:
% delete(L,E,LN) is true if a list LN is identical to a list L
% after removing all occurences of an element E.
delete([H|T],H,TN) :- delete(T,H,TN).
delete([H|T],E,[H|TN]) :- \+ H=E, delete(T,E,TN).
delete([],_,[]).
% unique(L,LN) is true if a list LN is identical to a list L
% without all repeated elements.
unique([H|T],[H|TU]) :- delete(T,E,TN), unique(TN,TU).
unique([],[]).
please guide here
thanks a lot
First of all you need to change
unique([H|T],[H|TU]) :- delete(T,E,TN), unique(TN,TU).
to:
unique([H|T],[H|TU]) :- delete(T,H,TN), unique(TN,TU).
What unique predicate does is to delete element duplicates in the list and keep only the first occurrence. But your predicate fails because you don't handle the case of empty list so if you add the clause:
unique([],[]).
It works fine:
?- unique([a,b,a,c],X).
X = [a, b, c].
In this example it calls unique([a,b,a,c],X). which calls delete([b,a,c],a,TN) and TN becomes [b,c] , calls unique([b,c],TU) and finally returns [a|TU].
TU is found recursively with the same way by calling:unique([b,c],TU)
which returns TU=[b|TU2] where TU2 given recursively by calling: unique([c],TU2) which returns [c].