Related
New to prolog and trying to implement the following function that takes 3 lists:
True if lists are the same length
True if elements of third list is sum of the two lists
Example: fn([1,2,3],[4,5,6],[5,7,9]) returns true. Note that the sum is element-wise addition.
This is what I have so far:
fn([],[],[]).
fn([_|T1], [_|T2], [_|T3]) :-
fn(T1,T2,T3), % check they are same length
fn(T1,T2,N1), % check that T3=T1+T2
N1 is T1+T2,
N1 = T3.
From what I understand, the error is due to the base case (it has empty lists which causes error with evaluation of addition?)
Thanks for any help and explanations!
In addition to #GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...
:- use_module(library(apply)). % for maplist/4
num_num_sum(X,Y,S) :-
S is X+Y.
... and subsequently use maplist/4 to apply it to entire lists:
fn(X,Y,Z) :-
maplist(num_num_sum,X,Y,Z).
This predicate yields the desired results if the first two lists are fully instantiated:
?- fn([1,2,3],[4,5,6],X).
X = [5,7,9]
However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:
?- fn([1,A,3],[4,5,6],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is _+B: expected bound value
?- fn([1,2,3],[4,5,A],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is A+B: expected bound value
If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:
:- use_module(library(apply)).
:- use_module(library(clpfd)). % <- use CLP(FD)
int_int_sum(X,Y,S) :-
S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2
fnCLP(X,Y,Z) :-
maplist(int_int_sum,X,Y,Z).
With this definition the previously problematic queries work as well:
?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
A = 2
?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
A = 6
Even the most general query yields results with this version:
?- fnCLP(X,Y,Z).
X = Y = Z = [] ? ;
X = [_A],
Y = [_B],
Z = [_C],
_A+_B#=_C ? ;
X = [_A,_B],
Y = [_C,_D],
Z = [_E,_F],
_A+_C#=_E,
_B+_D#=_F ? ;
.
.
.
Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:
label the lists
restrict the domain | |
v v v v
?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
X = Y = Z = [] ? ;
X = [3],
Y = [6],
Z = [9] ? ;
X = [3],
Y = [7],
Z = [10] ? ;
.
.
.
X = [3,4],
Y = [6,7],
Z = [9,11] ? ;
X = [3,4],
Y = [6,8],
Z = [9,12] ? ;
.
.
.
On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.
From what I understand, the error is due to the base case.
I don't see it that way.
The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.
When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.
e.g. for length of list you would have
ln([],N,N).
ln([_|T],N0,N) :-
N1 is N0+1,
ln(T,N1,N).
ln(L,N) :-
ln(L,0,N).
The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln([],N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.
Now back to your problem.
The base case is fine
fn([],[],[]).
There are three list and for each one look at the list as [H|T]
fn([H1|T1],[H2|T2],[H3|T3])
and the call to do the recursion on the tail is
fn(T1,T2,T3)
all that is left is to process the heads which is
H3 is H1 + H2
putting it all together gives us
fn([],[],[]).
fn([H1|T1], [H2|T2], [H3|T3]) :-
H3 is H1 + H2,
fn(T1,T2,T3).
and a quick few checks.
?- fn([],[],[]).
true.
?- fn([1],[1],[2]).
true.
?- fn([1,2],[3,4],[4,6]).
true.
?- fn([1,2],[3,4,5],[4,6,5]).
false.
With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.
I need to create a rule that has an input list and then takes values from it 2 at a time, compares them and creates a new list with the bigger values.
It needs to work like this:
INPUT: bigger([1,2,6,8,5], X).
OUTPUT: X = [2,6,8,8,5].
Here's my code:
%stop
bigger([],_).
%last element
bigger([H1|[]],L2):-
append(L2, [H1], L3),
bigger([],L3).
%compare first 2
bigger([H1,H2|T], L2):-
( H1 > H2,
append(L2, [H1], L3),
bigger([H2|T], L3) )
;
( H2 > H1,
append(L2, [H2], L3),
bigger([H2|T], L3) ).
If I replace the base case with
%stop
bigger([],L):-
write(L).
then I will get this output:
[2,6,8,8,5]
X = [] ;
[_G3685,2,6,8,8,5]
X = [_G3685] ;
[_G3685,_G3691,2,6,8,8,5]
X = [_G3685, _G3691] ;
[_G3685,_G3691,_G3697,2,6,8,8,5]
X = [_G3685, _G3691, _G3697]
.
I can see that at when it reaches the base case technically the second variable has the correct value. But then it unifies to an empty list. Not only that but it continues to add unknown elements.
How do I deal with this?
There are some things you need to change. For example the clause :
bigger([H1|[]],L2):-
append(L2, [H1], L3),
bigger([],L3).
calls bigger([],L3) which matches with the clause bigger([],_). but '_' matches with anything so this gives you the unknown elements. It is not very good idea ti use append but it would be better to use pattern matching like:
bigger([],[]).
bigger([H],[H]).
bigger([H1,H2|T], [X|T1]):-
( H1 > H2->
X=H1,
bigger([H2|T], T1)
;H2 > H1->
X=H2,
bigger([H2|T],T1) ).
here you instantiate one element of the output list L3 in every recursive call and do the same with the rest until it has one element. The clause bigger([],[]). is useful only when the input is the empty list. When input is not empty the recursion stops when one element has left in the list. Also it is better to use -> for the if-else statement.
The result:
?- bigger([1,2,6,8,5], X).
X = [2, 6, 8, 8, 5] ;
false.
Again a Prolog beginner :-}
I build up a list element by element using
(1)
member(NewElement,ListToBeFilled).
in a repeating call,
(2)
ListToBeFilled = [NewElement|TmpListToBeFilled].
in a recursive call like
something(...,TmpListToBeFilled).
A concrete example of (2)
catch_all_nth1(List, AllNth, Counter, Result) :-
[H|T] = List,
NewCounter is Counter + 1,
(
0 is Counter mod AllNth
->
Result = [H|Result1]
;
Result = Result1
),
catch_all_nth1(T,AllNth,NewCounter,Result1),
!.
catch_all_nth1([], _, _, _).
As result I get a list which looks like
[E1, E2, E3, ..., Elast | _G12321].
Of course, the Tail is a Variable. [btw: are there better method to fill up the
list, directly avoiding the "unassigned tail"?]
I was now looking for a simple method to eliminate the "unassigned tail".
I found:
Delete an unassigned member in list
there it is proposed to use:
exclude(var, ListWithVar, ListWithoutVar),!,
[Found this too, but did not help as I do not want a dummy element at the end
Prolog list has uninstantiated tail, need to get rid of it ]
What I noticed is that using length\2 eliminate the "unassigned tail", too, and in addtion
the same List remains.
My Question is: How does it work? I would like to use the mechanism to eliminate the unassigned tail without using a new variable... [in SWI Prolog 'till now I did not get the debugger
entering length() ?!]
The example:
Z=['a','b','c' | Y],
X = Z,
write(' X '),write(X),nl,
length(X,Tmp),
write(' X '),write(X),nl.
13 ?- test(X).
X [a,b,c|_G3453]
X [a,b,c]
X = [a, b, c] .
I thought X, once initialized can not be changed anymore and you need
a new variable like in exclude(var, ListWithVar, ListWithoutVar).
Would be happy if someone explain the trick to me...
Thanks :-)
You're right about the strange behaviour: it's due to the ability of length/2 when called with unbound arguments
The predicate is non-deterministic, producing lists of increasing length if List is a partial list and Int is unbound.
example:
?- length([a,b,c|X],N).
X = [],
N = 3 ;
X = [_G16],
N = 4 ;
X = [_G16, _G19],
N = 5 ;
...
For your 'applicative' code, this tiny correction should be sufficient. Change the base recursion clause to
catch_all_nth1([], _, _, []).
here are the results before
4 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d|_G75].
and after the correction:
5 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d].
But I would suggest instead to use some of better know methods that Prolog provide us: like findall/3:
?- findall(E, (nth1(I,[a,b,c,d],E), I mod 2 =:= 0), L).
L = [b, d].
I think this should do it:
% case 1: end of list reached, replace final var with empty list
close_open_list(Uninstantiated_Var) :-
var(Uninstantiated_Var), !,
Uninstantiated_Var = '[]'.
% case 2: not the end, recurse
close_open_list([_|Tail]) :-
close_open_list(Tail).
?- X=[1,2,3|_], close_open_list(X).
X = [1, 2, 3].
Note that only variable X is used.. it simply recurses through the list until it hits the var at the end, replaces it with an empty list, which closes it. X is then available as a regular 'closed' list.
Edit: once a list element has been assigned to something specific, it cannot be changed. But the list itself can be appended to, when constructed as an open list ie. with |_ at the end. Open lists are a great way to build up list elements without needing new variables. eg.
X=[1,2,3|_], memberchk(4, X), memberchk(5,X).
X = [1, 2, 3, 4, 5|_G378304]
In the example above, memberchk tries tries to make '4', then '5' members of the list, which it succeeds in doing by inserting them into the free variable at the end in each case.
Then when you're done, just close it.
Im trying to swap the first and last element of a list in haskell. I've tried pattern matchnig, expressions, functions, etc. This is my last attempt:
cambio xs = [ cabeza++([x]++cola)|x<-xs, cabeza <- init x, cola <- last x, drop 1 x, drop 0 ([init x])]
My compiler throws the next error:
Couldn't match expected type `Bool' with actual type `[a0]'
In the return type of a call of `drop'
In the expression: drop 1 x
In a stmt of a list comprehension: drop 1 x
Can anyone help me? I've tried to do this for 2 days
Here are a few hints:
You can't solve this with list comprehension.
Identify the base (trivial) cases - empty list and list of one element. Write equations that cover those cases.
In all other cases the length of the input list will be >= 2. The list you want is
[z] ++ xs ++ [a]
where z is the last element, a the first element of the input list and xs the middle part of the input.
Now tell me (or yourself), how long will xs be, if the length of the input string was k?
Write the equation that covers the case of lists with more than 1 elements. You can use functions like head, last, length, drop or take.
I think that lists aren't the best data structure for doing this, but here it goes:
swap list = last list : (init . tail $ list) ++ [head list]
This is going to require traversing the list and will be slow on long lists. This is the nature of linked lists.
Updated with base cases from question asker:
swap [] = []
swap [a] = [a]
swap list = last list : (init . tail $ list) ++ [head list]
This is a fairly straightforward thing to do, especially with the standard list functions:
swapfl [] = []
swapfl [x] = [x]
swapfl (x:xs) = (last xs : init xs) ++ [x]
Or without them (although this is less readable and usually not done, and not recommended):
swapfl' [] = []
swapfl' [x] = [x]
swapfl' (x:xs) = let (f, g) = sw x xs in f:g
where sw k [y] = (y, [k])
sw k (y:ys) = let (n, m) = sw k ys in (n, y:m)
Or one of many other ways.
I hope that helps ... I know I didn't do much explaining, but frankly, it's hard to tell exactly what you were having trouble with as far as this function is concerned, seeing as you also seem to completely misunderstand list comprehensions. I think it might be most beneficial if I explain those instead?
And why this cant be solved with a list comprehension? I tough they were like functions but with a different form
Not really. List comprehensions are useful for easily defining lists, and they're very closely related to set-builder notation in mathematics. That would not be useful for this particular application, because, while they're very good at modifying the elements of a list, comprehensions are not very good at reordering lists.
In a comprehension, you have three parts: the definition of an element in the list, one or more input lists, and zero or more predicates:
[ definition | x <- input1, y <- input2, predicate1, predicate2 ]
The definition describes a single element of the list we're making, in terms of the variables the arrows in the inputs are pointing at (x and y in this case). Each input has a list on the right of the arrow, and a variable on the left. Each element in the list we're making is built by extracting each combination of elements from the input lists into those variables, and evaluating the definition part using those values. For example:
[ x + y | x <- [1, 3], y <- [2, 4] ]
This generates:
[1 + 2, 1 + 4, 3 + 2, 3 + 4] == [3, 5, 5, 7]
Also, you can include predicates, which are like filters. Each predicate is a boolean expression defined in terms of the input elements, and each is evaluated whenever a new list element is. If any of the predicates come out to be false, those elements aren't put in the list we're making.
Let's look at your code:
cambio xs = [ cabeza++([x]++cola) | x<-xs, cabeza <- init x, cola <- last x,
drop 1 x, drop 0 ([init x])]
The inputs for this comprehension are x <- xs, cabeza <- init x, and cola <- last x. The first one means that every element in xs is going to be used to define elements for the new list, and each element is going to be named x. The other two don't make any sense, because init and last are type [a] -> a, but are on the right side of the arrow and so must be lists, and x must be an element of a list because it's on the left side of its arrow, so in order for this to even compile, xs would have to be type [[[a]]], which I'm sure is not what you want.
The predicates you used are drop 1 x and drop 0 [init x]. I kind of understand what you were trying to do with the first one, dropping the first element of the list, but that wouldn't work because x is just an element of the list, not the list itself. In the second one, drop 0 means "remove zero elements from the beginning of the following list", which would do absolutely nothing. In either case, putting something like that in a predicate wouldn't work because the predicate needs to be a boolean value, which is why you got the compiler error. Here's an example:
pos xs = [ x | x <- xs, x >= 0 ]
This function takes a list of numbers, removes all the negative numbers, and returns the result. The predicate is the x >= 0, which is a boolean expression. If the expression evaluates to false, the element being evaluated is filtered out of the resulting list.
The element definition you used is cabeza ++ [x] ++ cola. This means "Each element in the resulting list is itself a list, made up of all elements in the list cabeza, followed by a single element that contains x, followed by all elements in the list cola", which seems like the opposite of what you were going for. Remember that the part before the pipe character defines a single element, not the list itself. Also, note that putting square brackets around a variable creates a new list that contains that variable, and only that variable. If you say y = [x], this means that y contains a single element x, and doesn't say anything about whether x is a list or not.
I hope that helps clear some things up.
append([],Xs,Xs).
append([Head|Tail],List2,[Head|Tail2]):-
append(Tail,List2,Tail2).
The upper append method adds elements from first two parameter slots to the third param variable.
?-append([2,1], [3,4], X).
?-X=[2,1,3,4]
The way I see it in steps is (which is propably wrong):
append(2 | [1], [3,4], 2 | X)
append([1], [3,4], X)
append(1 | [], [3,4], 1 | X)
append([], [3,4], [3,4])
And that's it. I can't wrap my head around how it adds together the elements and that's what i could use help with - a clear explanation on how this method works. I just don't understand how the [2,1] array gets added to the final result.
the X in the recursion is not the same X as in the original call if you rename it in the trace you'll see
append(2 | [1], [3,4], 2 | X1) -- X = [2|X1]
append([1], [3,4], X1)
append(1 | [], [3,4], 1 | X2) -- X1 = [1|X2]
append ([], [3,4], [3,4]) -- X2 = [3,4]
so X1 = [1,3,4] and X = [2,1,3,4]
First, you have to understand how a list is implemented in Prolog. It is an essentially recursive data structure.
The empty list is a list of zero items, represented by the atom [].
Non-empty lists are represented by the structure ./2, consisting of the head of the list (a prolog term), and the tail of the list (another list, consisting of all items save the first). So...
[] — a list of zero items, is represented as[]
[a] — a list of 1 item, is represented as.(a,[])
[a,b] — a list of 2 items, is represented as.(a,.(b,[]))
[a,b,c] — a list of 3 items, is represented as .(a,.(b,.(c,[])))
The standard list notation using square brackets is just syntactic sugar on top of this representation. Saying [Head|Tail] is a polite way of saying .(Head,Tail) and saying [X,Y,Z|More] is the polite way of saying .(X,.(Y,.(Z,More))). (You might be noticing a certain....Lisp-ishness...to the internal list notation here.)
Understanding how a list is represented, the naive algorithm for appending (concatenating) one list to another is this:
First, there are two special cases to consider:
The result of appending a non-empty list X to an empty list Y is X.Append [1,2,3] to [] and get [1,2,3].Note. This case is can be (is normally) handled by the ordinary case below, though. It's an opportunity for optimization as there's no point in recursing down the entire list, just to replace [] with [] at the end, right?.
The result of appending an empty list X to a non-empty list Y is Y.Append [] to [1,2,3] and you get [1,2,3].
Otherwise, we have the ordinary case:
Append non-empty list Y to non-empty list X to produce list Z. To do this is trivial:
We simply recurse down on list X, popping its head as we go and and prepending that to list Z, the result. You'll notice that as this happens, list Z is a broken list structure, since its last node is always unbound rather than being []. This gets fixed at the very end when the source list, list X, is exhausted and degenerates into the special case of being an empty list. At that point, the unbound last node gets bound as it unifies with list Y (a list of zero or more nodes), leaving us with a correct list structure.
The Prolog code for append/3 expresses this algorithm directly. As noted earlier, the first clause is an optional optimization, as that can be handled by the 3rd clause (the ordinary case). It wants a cut, though, as without, backtracking would produce two solutions.
append( X , [] , X ) :- !. ; concatenate empty list X to list Y producing Y
append( [] , Y , Y ). ; concatenate list X to empty list Y producing X
append( [X|Xs] , Y , [X|Zs] ) :- ; anything else
append( Xs , Y , Zs )
.