I am trying to understand prolog through examples. I wrote a piece of code but it is not working in desired manner and I am unable to find the fault.
list([]).
test([],_,_).
test([Child|List],B,C) :-
append([Child],B,C),
test(List,B,C).
testme :-
list(Final),
test([1,2,3],Final,Result),
write(Result).
The functionality which I require from this code that the Result should be the reverse of input list. When I trace this code I found the reverse of input list in C but it is not returned.
I knows using reverse function I can easily find reverse of list but my interest is not in finding the reverse but to understand this code and working of prolog. So please can someone tell me where I am wrong and what modification is required in this code to work properly.
First let's see why your code does not work.
test([],_,_).
test([Child|List],B,C) :-
append([Child],B,C),
test(List,B,C).
You tried to define a recursive predicate with two clauses.
The arguments to this predicate are: the input list (1), an intermediate list (2) and the final result(3).
Your first clause is thus, wrong.
Suppose your input list is just an empty list. The result should be an empty list. But in your first clause you are leaving the third argument as-is. Either it was already bound to somenthing (not useful in this case) or it was unbounded and therefore it will keep that way.
The second clause deals with recursion. It takes the first element of your input list, append it in the front of the intermediate list yielding another intermediate list.
Now you do the recursion step calling test again. But note that now the three arguments are instantiated! so you won't be able to append another item to the final list.
Here goes your test/3 predicate modified to work as you expect:
test([],List,List).
test([Child|List],B,D) :-
append([Child],B,C),
test(List,C,D).
Now the first clause just unifies the second and third argument.
So in our first test case (empty input list), recall that the second argument was also an empty list, so the third argument will also be an empty list => correct.
Now for the recursive clause.
It will take the first element of the input list and append it to the intermediate list, and unify it on a fresh variable.
Now we go into the recursion step, but now we use that list (C) as the intermediate list.
This, on recursion, will build the output list, now bound to D which is what we use as output.
As you are just appending one element to the intermediate list each time, you could have got rid of the append with something like:
test([],List,List).
test([Child|List],B,C) :-
test(List,[Child|B],C).
Prolog rules can only "return" values (since there is really no distinction between parameters and return values) by unifying them with their arguments. Assuming you want an accumulator-based reverse operation, you will need three parameters to test, and it should act as if it was written as:
test(A, B, C) :- reverse(A, A2), append(A2, B, C).
Having an implicit append operation in test will make the recursion easier to write. Also, note that you can write append([A], B, C) as C = [A | B] (or replace C by [A | B]).
Related
I have a list of list and a list. I want to update the list of list by using the element from the second list.
For example:
I have a list of list
[[banan,NA],[apple,NA]] and a list [sweet,notsweet],
want to update the list of the list, so I will have a list of list
[[banana,sweet],[apple,notsweet]]
I have tried the code below, but I think I cannot figured out the base case correctly.
update([[]],[],[]).
update([[T|_]|HH],[FB|H2],[NState|_]) :-
NState=[T|FB],
update(HH,H2,NState).
Any help, will be much appreciate
thanks
You're almost there. First let's observe that the first list is empty if there are no more [fruit,*] pairs left, hence the first argument of your base case should be []. At that point the other lists have to be empty too, since they are of the same length.
In general, the first list will have a two-element list as its head, the first of which is being your object of interest and the second of which you don't care for, that is, something like [X,_]. The tail of that list will contain further X's, so let's maybe call it Xs. Then the first argument looks like [[X,_]|Xs]. The second argument is a flat list, so you can write [Y|Ys] (read as: the list starts with a Y that is followed by further Y's). The last argument is a two-element list [X,Y] that is followed by other such pairs (XY's), hence: [[X,Y]|XYs]. The relation has to hold for the tails as well, that can be described by a recursive goal. You can express the above in Prolog like so:
update([],[],[]).
update([[X,_]|Xs],[Y|Ys],[[X,Y]|XYs]) :-
update(Xs,Ys,XYs).
With these alterations to your predicate the example query from your comment yields the desired answer:
?- update([[banana,*],[apple,*]],[sweet,notsweet],C).
C = [[banana, sweet], [apple, notsweet]].
I am new to Prolog and wanted to start learning the functionality of [H|T] by trying to write the prefix function on my own. The prefix function returns all possible prefixes to a list, such as for L = [a,b,c] would be [], [a], [a,b] and [a,b,c]. I am confused about how my own Prolog function would be able to return so many different solutions. I have it splitting the head and tail of the list, and appending the head to my new list that is going to be the different prefixes returned. This is what I have so far, but I think I am oversimplifying, and don't know how else to recursively call it to get all the different possibilities.
myPrefix([],[]).
myPrefix([H|T],List) :- myPrefix(T, [H|List]).
I looked at a lot of the other answers, but those just deal with getting the first element off of a list, not listing all possible prefixes. Any advice of how to go from here or more explanation as to how this head and tail of list manipulation functionality works is appreciated.
Assuming the first argument if instantiated is indeed is a proper list, then this should do it:
myPrefix(_, []).
myPrefix([H|T], [H|NT]):-
myPrefix(T, NT).
First clause ignores the first argument and unifies the second with the empty list.
Second clause takes the head of first argument list and puts it as the head of the second argument, and calls itself recursively.
So in effect, the second clause takes one by one as many items as desired and the first clause drops the tail.
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 can't understand clearly the use of cut. For example in this case: flatten, is it really needed? It works for me even without both cut predicates (I tried removing). What are the cases that can cause the backtracking going to the cut?
Removing the cuts you have the same implementation of the book "The art of prolog" (Shapiro E.,Sterling L.) that is:
flatten([X|Xs],Ys) :-
flatten(X,Ysl),
flatten(Xs,Ys2),
append(Ys1,Ys2,Ys).
flatten(X,[X]) :-
constant(X),
X\=[].
flatten([],[]).
which leads me to another question: is it necessary in the second clause to check if it's not a list? If it's a single term won't unify with the first clause...isn't it?
The program linked in your question uses cut ! operator to prevent the code in the answer from unifying with other clauses. Without these cuts flatten2/2 from the answer would unify an empty list in the first argument with clauses one and three, i.e.
flatten2([], []) :- !.
flatten2(L, [L]).
Similarly, without a cut in the second clause flatten2/2 would unify a non-empty list in clauses two and three, leading to incorrect behavior.
Your code, on the other hand, has explicit checks to ensure that each clause of flatten/2 deals with one specific situation:
First clause recursively flattens non-empty lists
Second clause makes a single-item list from constants other than empty lists
Third clause "flattens" empty lists.
Since each clause applies exclusively to a single type of item on the left, the cut is not necessary. You could have rewritten your code with a cut by switching the second and the third clause, and adding a cut after matching an empty list, but I would strongly recommend against doing this (demo).
is it necessary in the second clause to check if it's not a list?
This check is necessary because an empty list [] is considered a constant, so your program would have incorrect behavior when empty lists are present in the list being flattened (demo).
While learning Prolog, I'm trying to solve the following problem, using accumulators:
Write a predicate addone2/ whose first argument is a list of integers, and whose second argument is the list of integers obtained by adding 1 to each integer in the first list. For example, the query
addone([1,2,7,2],X).
should give
X = [2,3,8,3].
I created the following code:
addone([], _).
addone([E|Tail], [R|Rs]) :-
NewE is E+1,
append([R|Rs], [NewE], NewRs),
addone(Tail, NewRs).
But it's not working. Can someone tell me why? So, how do I use accumulators in Prolog?
Thanks!
anthares is correct in that you have to refine your base case. However, you are also making things very inefficiently with your append calls. In Prolog, it takes some time to get used to the power of unification, but for example, in this case it helps you to immediately set up your result list. Try the following:
addone([E|Tail], [E1|Rs]) :-
E1 is E+1,
addone(Tail, Rs).
That's really all there is to it. By immediately placing E1 in your second argument's pattern, you have already created the first element of your result list. The remaining elements Rs will be created during the recursion. A very typical Prolog pattern.
The bottom of your recursion should be addone([],[]). in order NewRs to be connected with the []