I am attempting to remove unique elements from a list in Prolog.
Output should look something like:
?- rem_Uniq([3,3,1,7,a,c,c],D).
D = [3, c].
Here is my current code.
rem_Uniq(L1,L2).
rem_Uniq([L1|RL1], [L1|D]) :-
member(L1,RL1),
rem_Uniq(RL1,D).
rem_Uniq([L1|RL1], D) :-
remove(L1[L1|RL1], O),
rem_Uniq(O, D).
Currently it just returns true no matter what I do (whether I enter I list containing unique variables or not).
Anyone have any ideas or suggestions on what I am doing wrong?
D is the set of elements of the list which appears only one time.
In Prolog "an element which appears only one time in a list" can be translate by
select(X, L, L_X),
\+member(X, L_X)
In Prolog exist predicates that collect element with a certain property setof/3 and bagof/3.
bagof collect all the elements, setof keeps only one element.
So you can write
rem_uniq(In, Out) :-
setof(X, In_X^(select(X, In, In_X),\+member(X, In_X)), Out).
[EDIT]
Now we want only elements that are duplicated in a list. If I remove one of these elements of the list, it will remain other elements of the same value in the list so it can be translated in Prolog by
select(X, In, In_X),
member(X, In_X)
(we say that select(X, In, In_X),member(X, In_X) succeed).
Now the code can be written
rem_uniq(In, Out) :-
setof(X, In_X^(select(X, In, In_X),member(X, In_X)), Out).
For example
?- rem_uniq([3,3,1,7,a,c,c],D).
D = [3,c].
Note that setof will fail if there no elements available
?- rem_uniq([3,1,7,a,c],D).
false.
Well, your first problem is your first clause:
rem_Uniq(L1,L2).
This literally says "Any two things are rem_Uniq to each other." This is what's giving rise to always getting true with no unifications. You probably meant this:
rem_Uniq([], []).
Your second problem is that this is not valid syntax:
remove(L1[L1|RL1], O),
Specifically, L1[L1|RL1], I am unclear what you meant there. I think you meant this delete(L1, [L1|RL1], O).
Now, algorithmically, I think you're a little confused. In clause #2, you prepend L1 to D in the result, which is to say, after knowing that L1 is present in RL1 and using the recursive call to remove it from D. But then in clause #3, you just remove it from [L1|RL1] to make O, which you then remove uniques from.
Each clause of a recursive predicate should represent a case you have to worry about. I don't really see what these clauses mean. The first one should be, in case where the list is empty. The second one should be the case where the list is not empty. What you seem to be trying to do here is something like, in the case where the list is not empty and contains the head element, and the case where it is not empty and does not contain the head element, but the distinction between having or not having that element is (or ought to be) meaningless to your library routine. In other words, delete/3 in one non-empty recursive case should be totally sufficient for this problem:
rem_uniq([], []).
rem_uniq([X|Xs], [X|UniqueXs]) :-
delete(X, Xs, XsWithoutX),
rem_uniq(XsWithoutX, UniqueXs).
So, I think you have a little confusion about when and why you should have multiple clauses, and I think your choice of variable names may have made life harder on yourself. But that's just my guess.
Hope this helps!
Related
Write a PROLOG program (i.e., set of predicates) that implements the following function. The program should compare three lists and determine if the first element of the first list is the same as both the last element of the second list and the second to last element of the third list. Call the main predicate: compare(List1, List2, List3).
I went ahead and wrote separate codes for the two separate conditions, which works on its own.
1. 1st item of List1 equals last item of List2.
2. 1st item of List1 equals second to last item of List3.
Now I'm having trouble combining the codes to work together. My train of thought is that condition 1 and condition 2 have to be met separately before the overall condition is met. So somehow I have to run the code for condition 1 and condition 2 on its own but in the same program?? And if both of those return true then I can have something else that says my conditions are met.
compare(List1,List2,List3):- last(true), secondLast(true).
Condition1:
last([HeadList1|RestList1],[HeadList1]).
last([HeadList1|RestList1],[HeadList2|RestList2]) :-
last([HeadList1|RestList1],RestList2).
Condition2:
secondLast([HeadList1|RestList1],[HeadList1,RestList3]).
secondLast([HeadList1|RestList1],[HeadList3|RestList3]) :-
secondLast([HeadList1|RestList1],RestList3).
What I'm expecting:
?- compare([2,8,9,1],[4,5,6,2],[1,2,3]).
yes
?- compare([a,b,c,d,k],[a,c,f,e],[a,s]).
no
With SWI, you can use last/2 and the definition of secondTast/2 from this question:
secondLast([X,_], X).
secondLast([_|T], X) :- secondLast(T, X).
my_compare([H|_],L1,L2):-
last(L1,H),
secondLast(L2,H).
?- my_compare([2,8,9,1],[4,5,6,2],[1,2,3]).
true
?- my_compare([a,b,c,d,k],[a,c,f,e],[a,s]).
false
You can put a cut to avoid the solution false in the first query. This is a first solution, you can get super fancy and use for instance reverse/2 and other predicates to find another solution (but maybe slower).
#damianodamiano suggests an implementation using reverse/2 and I thought it might be interesting to see what it is.
mycompare([H|_], L2, L3) :-
reverse(L2, [H|_]),
reverse(L3, [_, H|_]).
reverse/2 is somewhat more expensive than a list traversal, so this may not be the best way to solve the problem, I think it's worth seeing because it's fairly close to the question as stated and it demonstrates that this problem is solved really by unification and only unification. damianodamiano's solution has a similar property in that you are finding the first thing, H and then showing that H appears in other positions in the other two lists.
Now I have some miscellaneous feedback for you:
You are right to believe that if you have two predicates, say p1 and p2, you can combine them by doing p1, p2. In general, they are going to share variable bindings between them because what you are doing in programming in Prolog is setting up a relationship between certain things.
This is also why singleton "warnings" are actually errors: they reveal cases where you believe there is a relationship, but where Prolog could tell that you didn't share the variable anywhere, so no relationship was established.
Your variable names are really bad. If 99% of all your variable names are the same, you are going to get confused. It would be better to use A and B than HeadList1 and HeadList2. If you must use names like these, simplify to H1 and H2. When you see [X|Y], you know X is a head of a list and Y is a list tail, you do not need to make that information part of the name. Focus on the content of the variable if you can, or the relationship you're trying to establish between the expressions that variable is a part of.
Prolog predicates do not "return true." They can succeed or fail but they are not evaluated like functions: you cannot replace mycompare(A,B,C) with true just because mycompare(A,B,C) succeeds, you cannot assign a value to the result R = mycompare(A,B,C), and you cannot nest predicates like writeln(mycompare(A,B,C)). So break this habit now so you don't confuse yourself further in the future.
Hey so this is my code so far. I am only a begginer in prolog but i need it for school
firstElement([_|_], [Elem1|List1], [Elem2|List2]):-
Elem1 =< Elem2, merge([Elem1] , List1, [Elem2|List2]);
merge([], [Elem2], List2).
merge([Head|Tail], [Elem1|List1], [Elem2|List2]):-
Elem1 =< Elem2,!, add(Elem1,[Head|Tail],[Head|Tail1]),
merge([Head|Tail1], List1, [Elem2|List2]);
add(Elem2,[Head|Tail],[Head|Tail1]),
merge([Head|Tail1], [Elem1|List1], List2).
merge([Head|Tail], [], [Elem2|List2]):-
add(Elem2,[Head|Tail],[Head|Tail1]).
merge([Head|Tail], [Elem1|List1], []):-
add(Elem1,[Head|Tail],[Head|Tail1]).
merge([Head|Tail], [], []).
add(X,[],[X]).
add(X,[Y|Tail],[Y|Tail1]):-
add(X,Tail,Tail1).
I found out that everytime it gets out of a merge it keeps forgetting the last number so it gets back to nothing in the end.
I think you’ve gotten very mixed up here with your code. A complete solution can be had without helpers and with only a few clauses.
First let us discuss the two base cases involving empty lists:
merge(X, [], X).
merge([], X, X).
You don’t quite have these, but I see some sort of recognition that you need to handle empty lists specially in your second and third clauses, but I think you got confused and overcomplicated them. There’s really three scenarios covered by these two clauses. The case where both lists are empty is a freebie covered by both of them, but since that case would work out to merge([], [], []), it’s covered. The big idea here is that if you exhaust either list, because they were sorted, what you have left in the other list is your result. Think about it.
This leaves the interesting case, which is one where we have some items in both lists. Essentially what you want to do is select the smaller of the two, and then recur on the entire other list and the remainder of the one you selected the smaller value from. This is one clause for that:
merge([L|Ls], [R|Rs], [L|Merged]) :-
L #< R,
merge(Ls, [R|Rs], Merged).
Here’s what you should note:
The “result” has L prepended to the recursively constructed remainder.
The recursive call to merge rebuilds the entire second list, using [R|Rs].
It should be possible to build the other clause by looking at this.
As an intermediate Prolog user, I would be naturally a bit suspicious of using two clauses to do this work, because it’s going to create unnecessary choice points. As a beginner, you will be tempted to erase those choice points using cuts, which will go badly for you. A more intermediate approach would be to subsume both of the necessary clauses into one using a conditional operator:
merge([L|Ls], [R|Rs], [N|Ns]) :-
( L #< R ->
N = L, merge(Ls, [R|Rs], Ns)
; —- other case goes here
).
An expert would probably build it using if_/3 instead:
#<(X,Y,true) :- X #< Y.
#<(X,Y,false) :- X #>= Y.
merge([L|Ls], [R|Rs], [N|Ns]) :-
if_(#<(L,R),
(N = L, merge(Ls, [R|Rs], Ns)),
( -- other case here )).
Anyway, I hope this helps illustrate the situation.
I find myself narrowing a (very simple) problem more and more.
Let's say I have this operation: listsplit([H1,H2,H3|T], H1,H2,H3, T).
Which gives me the first three elements of a list. I want a program, cells, to travel an input list and make (at least that ONE operation!!) to every element of the list.
So I have something like:
cells(Input, Result):-
cellsBody(Input, [], Result).
cellsBody([],Result,Result).
cellsBody([Head|Input], Acc, [Headd|Result]):-
listsplit(Input,H1,H2,H3,_),
cellsBody(Input, [OutputBody|Acc], Result).
I have that code because I have used many I've seen as examples that go like that to travel a list. They separate head from body and go on. I fail to see how this is done in prolog. I tried changing variable names, so that they would match (as I would do in other languages), and I've tried to make the problem as simple as possible.
So, how do I travel a list AND make operations to every element (that I choose to, starting with the first one, the head).
Edit: Examples of what I want to archieve:
I get an input list like oxo, oxxxo, oxoxo, so on. I then apply a rule to the first three elements, then the next three, and so on, and while I do that I add the result of the rule to another list that I return (which is why I am trying to use the accumulator).
You've almost got it. Keeping your predicate cells/2 as is, think about the special cases first: The lists [], [_], [_,_] haven't got three elements, so whatever operation you have in mind for those three elements, there's nothing to do in these cases. Otherwise you have a recursive rule to do what you intend to.
Looking at listsplit/5: you can do that directly in the head of the recursive rule, no need for an extra predicate. Then you have one or more goals for your intended operation. For the sake of an example let's say packaging the 3 head elements as a triplet. And of course the relation must hold for the tail T of the list too. Then your code might look something like that:
cellsBody([],Result,Result).
cellsBody([_],Result,Result).
cellsBody([_,_],Result,Result).
cellsBody([H1,H2,H3|T], Acc, Result):- % the first 3 elements
Triplet=(H1,H2,H3), % at least ONE operation with them
cellsBody(T, [Triplet|Acc], Result).
Example queries:
?- cells([],Result).
Result = []
?- cells([1],Result).
Result = []
?- cells([1,2],Result).
Result = []
?- cells([1,2,3],Result).
Result = [(1,2,3)]
?- cells([1,2,3,4,5,6,7],Result).
Result = [(4,5,6),(1,2,3)]
Of course, if the intended operation is as simple as in the above example, you don't need an extra goal for it: You can do that directly in the recursive goal:
cellsBody([H1,H2,H3|T], Acc, Result):-
cellsBody(T, [(H1,H2,H3)|Acc], Result).
I am new in Prolog and I am studying it for an universitary exam, we use SWI Prolog
I have some problem to understand how work this simple program that say TRUE if a list S is a sublist of a list L, otherwise say that the predicate is FALSE.
I have the following solution but I have some problem to understand it's declarative meaning
Reading the book I think that I had have some idea but I am not sure about it...
This is the solution that use concatenation:
sublist(S,L) :- conc(L1, L2, L),
conc(S, L3, L2).
conc([],L,L).
conc([X|L1],L2,[X|L3]) :- conc(L1,L2,L3).
This solution use an other litle program that respond TRUE if the third list is the concatenation of the first and the second list.
To say if S i sublist of L have to be TRUE the following two conditions:
L have to be a list that is the concatenation of L1 and L2
L2 have to be a list that is the concatenation of S (my sublist if exist into L list) and another list L3
This is the book explaination but it is just a litle obsucre for me...
I have try to reasoning about it and try to understand what really deeply mean...
So I think that, in some way, it is like to search if an element is member of a list using this other program:
member2(X, [X|_]).
member2(X,[_|T]):- member2(X,T).
In this program I simply say that if X is the element in the top of the list (its head) then X is in the list and the program respond true. Otherwise, if X element is not in the top of the list (or it is not my solution) I try to search it it the TAIL T of this list.
Back to the sublist program I think that the reasoning is similar
First I decompose L list in two list L1 and L2 (using conc program)**
Then I check if it is true that the concatenation of S and L3 is the L2 list.
If booth these condition it is true then S is sublist of L
I think that the L1 list have a similar role of the X element that I extract from the list in the member program.
Since the sublist S can start at the beginning of the list L, L1 can be [] and I have that I can decompose L in the concatenation of L1=[] and L2 and the I can try to decompose L2 in S and L3.
If I can do this last decomposition then the program end and I can say that it is true that S is a sublist of the original list L
If it is not true that conc(S, L3, L2) then ddo backtrack and take an other branch of computation
Is it right my declarative interpretation?
I am finding great difficulties with this example, I have also try to find a procedural explaination (using the operation trace in the Prolog shell) but I have big problem because the computation it is so big also for a short list...
The book explanation is more declarative, because it doesn't invoke Prolog's search mechanism. I would probably write this with more underscores:
sublist(S, L) :- append(_, Suffix, L), append(S, _, Suffix).
This at least makes the relationship between S and L2 (renamed Suffix) a little more clear. What we're trying to say, and this is hard to express clearly in declarative English, is that S is a sublist of L if there is a suffix of L called Suffix and S is a prefix of Suffix. Naming the other constituents only adds confusion. Prolog will internally name these variables and unify something with them as it attempts to unify everything else, but it won't share that information with the caller. Though these variables need to exist in some sense, they aren't germane to your formula or they would not be singletons. Whenever you get a singleton variable warning, replace the variable with the underscore. It will add clarity.
It happens that since the prefixes and suffixes involved can be empty lists, S can be a proper prefix of L or a proper suffix of L and everything will work out.
The declarative reading of member/2, for reference, is X is a member of a list if X is the head of the list or if X is a member of the tail of the list. Note carefully what is absent: mention of checking, success or failure, or, really, any order of operations. It is equally declarative to say X is a member of a list if it is a member of the tail or if it is the head. It is just an unavoidable fact of life that to make a computer perform a calculation it must be done in a certain order, so you have to tell Prolog things in the right order or it will enter infinite loops, but this is not an aspect of logic, just Prolog.
As we've gone over several other times, when you invoke the machinery of Prolog, you are no longer in a declarative reading. So when you say, for instance "First I decompose..." you've already left the declarative world and entered the procedural world. The declarative world doesn't have steps, even though Prolog must do things in a certain order to perform a computation on a real-life computer. Likewise, in a declarative reading you do not check things, they simply are or are not. The word backtrack also cannot appear as part of a declarative reading. The only "verb" you should be using in a declarative reading is the verb of being, "is."
That said, your Prolog/procedural readings are perfectly correct.
Hey guys, a few simple prolog questions that I'm hoping you can help me on. Basically, I am trying to write a function that takes input as two lists, and an integer. From there, the function will try to find an x in the first list and a y in the second list such that x + y is equal to the input integer.
So far I am thinking to just recurse down by doing something such as follows:
sum([H1|T1], [H2|T2], Value) :-
NewVal is H1+H2
% Check for equality?
sum(List1, T2, Value)
sum(T1, List2, Value).
So, a few questions regarding this method.
1) How do I refer the the "whole" list after I've passed it in as H1|T1? In the example I just named them List1 and List2 for reading ease.
2) I can check for equality, but how do I "stop" searching and force output?
You need a disjunction, not a conjunction: EITHER h1+h2 is ok, OR there is a solution without h1, OR there is a solution without h2.
There are two syntaxes in prolog for disjunction. You can use a semicolon:
sum([H1|T1], [H2|T2], Value) :- Value is H1+H2 ; sum([H1|T1], T2, Value) ; sum(T1, [H2|T2], Value).
Or you can use separate clauses:
sum([H1|_], [H2|_], Value) :- Value is H1+H2.
sum([H1|T1], [_|T2], Value) :- sum([H1|T1], T2, Value).
sum([_|T1], [H2|T2], Value) :- sum(T1, [H2|T2], Value).
IIRC, I think you should be able to pass the whole list as a parameter using [H1|T1].
Most likely you would want to use the Prolog cut, which stops searching for solutions.
1) Kaleb is right, to do this, just reconstruct the list as the head cons with the tail.
2) Jerome is right, but here's another way of putting it...
Your question "How do I make it stop?" actually hints at a missing part of your predicate. You currently have a recursive predicate with no base case - the recursion has no way of being able to stop. Well I guess in this case it will get to the end of one of the lists, but since this will then be the empty list it will then fail when being unified with the term [H|T] as there is no head item.
When writing a recursive predicate that is looking for a particular element of a list it is common to make the base contain the constraints which define the solution. You can see this in Jerome's solution. This results in a predicate that succeeds once it has found a solution and doesn't continue to process the list afterwards. It will however continue on after this point if you tell it to backtrack and look for more solutions. If you don't care about these further solutions, then you can use the cut to discard them.