I have this code for splitting input list into its halves. It seems to be OK.
halve(List,A,B) :- halve(List,List,A,B), !.
halve(B,[],[],B).
halve(B,[_],[],B).
halve([H|T],[_,_|T2],[H|A],B) :-halve(T,T2,A,B).
Ok, so I tried to decode it. The beginning is clear:
“Halve took list and 2 logic variables” is this:
halve(List,A,B)
(1) Then continuous this part:
:- halve(List,List,A,B).
And this means, that I am creating new two lists (List, List) from the first one or what? What exacly represents “:-“? I guess the new lists = halves will be the A, and B, right?
(2) Second, please, I don’t quite get these two lines:
halve(B,[],[],B).
halve(B,[_],[],B).
Maybe you could explain it on some examples, please?
(3) Well, I hope after your explanation of (1) and (2), I’ll get the final part by myself…
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Thank you very, very much for helping me.
Ok, our first problem already has its solution. Long story short, it works like this:
halve([1,2,3,4,5],[1,2],[3,4,5]).
->true
If you notice it splits the list into its halves but if the list has an odd number of the elements, the second half is the bigger one.
Now what I want to obtain is to have the first one bigger.
So I’m thinking about this:
I’m going to reach this:
Halves_div([1,2,3],A,B).
A=[1,2],
B=[3].
Let’s say my input is list: [1,2,3]. So I’ll start with splitting list’s head and tail: [H|T] and then I will merge the H with new empty list – my 1st Half (A).
After that I have A=[1], B=[] and Input=[2,3].
For merging I have:
merge([],List,List).
merge([H|T],List,[H|New]) :- merge(T,List,New).
And one more thing – I need to check whether the 1st half is already >= 2nd half, right?
So this is my idea and only thing I’d love you to help me is to write it in prolog. I’m kinda confused how to put it together.
Thanks!
It seems my idea of solution is too complicated and I found something better!
To start, a Prolog clause looks like that:
You can read that as “
HeadifBody“, or “BodyimpliesHead“.Note that sometimes you just have
That’s because Head is always
true. Instead of callingHeada clause, we rather call it a fact in this case.So here, we have:
That means that
halve(List, A, B)is true ifhalve(List, List, A, B)is true. Concretely it’s just a way to delegate the work ofhalve/3tohalve/4, a so called worker predicate.Why do we need a worker predicate? Well, because here we’d like to use another variable to calculate our
AandBterms. But we couldn’t do that withhalve/3because the 3 argument spots ofhalve/3were already taken by the input list,List, the first half of the result,Aand the second half of the result,B.About the
List, Listthing, it’s just a way to say that we callhalve/4with the same first and second argument, like you would in any programming language.Then the interesting stuff starts. Prolog will try to prove that
halve/4is true for some given arguments. Let’s say to illustrate the execution that we calledhalve/3this way:Then, if you followed what I talked about previously, Prolog will now try to prove that
halve/3is true by proving thathalve/4is true with the following arguments:halve([1, 2], [1, 2], A, B)..To do that, Prolog has 3 choices. The first choice is the following clause:
Obviously, that won’t work. Because when Prolog will try to fit the second argument of the caller “in” the second argument of the callee through unification, it will fail. Because
[1, 2]can’t be unified with[].Only two choices left, the next is:
Same thing here, Prolog cannot unify
[1, 2]and[_]because_is just a variable (see my post about the anonymous variable_if you’ve troubles with it).So the only chance Prolog has to find a solution to the problem you presented it is the last clause, that is:
Here, Prolog will find a way to unify thing, let’s see which way:
[1, 2]with[H|T]. That means thatH = 1.andT = [2].[1, 2]with[_,_|T2]. that means thatT2 = [].A = [H|A'](I primed the secondAbecause variables are scoped locally and they are not the same). Here we tell that when we’ll have our result calculated from the body of the clause, we’ll addHto it. HereHis1so we already know that the first element ofAwill be1.Ok ok, unification succeeded, great! We can proceed to the body of the clause. It just calls
halve/4in a recursive manner with those values (calculated above):And here we start all over again. Though this time things will be fast since the first choice Prolog has will be a good fit:
can be unified to
with those values:
A = []andB = [2].So that’s a good step, we now reached the “base case” of the recursion. We just have to build our result from bottom to top now. Remember when we called recursively our predicate
halve/4a few steps above? We had already said that the first element ofAwould be1. Now we know that the tail is[]so we can state thatA = [1]. We hadn’t stated anything particular aboutBsoB = [2]is left untouched as the result.Now that I detailed the execution, you might wonder, why does this work? Well, if you pay attention, you’ll note that the second argument of
halve/4is gone through twice as fast as the first one.[H|T]vs[_, _|T2]. That means that when we hit the end of the list with our second argument, the first one is still at the middle of our list. This way we can divide the thing in two parts.I hope I helped you catch some of the subtle things at work here.