Example:
?-lastN([1,2,3,4],3,T).
T = [2,3,4]
this is whay i'm write:
lastN(L,N,R):- length(L,X), X1 is X-N, lastT(L, N,R).
lastT(L,0,L).
lastT(X,[H|T],L):- X2 is X-1, lastT(T,X2,L).
I assume the question was 'predicate to get last N elements in a list' and this is what you meant to do. It's a simple discarding of the first element after counting how many elements have to be discarded, right? It also does not deal with improper input at all
lastN(L,N,R):- length(L,X), X1 is X-N, lastT(L,X1,R).
lastT(L,0,L).
lastT([H|T],X,L):- X2 is X-1, lastT(T,X2,L).
Related
I want to Display all list elements that larger than N, my code like
member2(X, [X|_]).
member2(X, [_|T]) :- member2(X,T), X > T, write(X).
Why would you state member2(X, [X|_]) ? Its not the last element yet. You should only stop when there are no more elements to check: member2(X,[]).
And generally:
member2(X,[Y|Ys]) :- (X >= Y -> display(Y), nl; true), member2(X,Ys).
This way you will display all the Ys that are smaller or equal to X.
In your code, T was a list of elements. You cannot compare it to a single elememt X.
You could use include/3 to perform the filtering. For example:
include(<(5),[7,3,2,6,4,5,8],Output).
will unify Output with [7,6,8] (the elements in the second argument that are greater than the number used in the first argument).
I am new to PROLOG and am trying some simple exercises to familiarize myself with it. However I am stuck in making an addition of 2x2matrix with another, more specifically lists within lists.
This is my code, the output using SWI-Prolog is False, and I have no idea why. Any help is appreciated!
matrixAdd([X],[Y],[S]) :- S is X + Y.
matrixAdd([[H|A],[I|B]],[[J|C],[K|D]],[[S1|Sum1],[S2|Sum2]]) :-
S1 = H + J,
S2 = I + K,
matrixAdd([A,B],[C,D],[Sum1,Sum2]).
Elaborating:
?- A = 2 + 3.
A = 2+3.
?- A = 2 + 3, A == 5.
false.
?- A = 2 + 3, A = 5.
false.
?- A is 2 + 3, A =:= 10/2.
A = 5.
?- A is 2 + 3, A = 10/2.
false.
Figure out why you get each of these answers.
Furthermore, think about how you want to represent your matrix. Does it need to be a nested list? For example, it could be something like matrix(dim(2,2), [1,2,3,4]). Then, adding two matrices would be as easy as:
matrix_sum(matrix(D, V1), matrix(D, V2), matrix(D, Sum)) :-
maplist(add, V1, V2, Sum).
add(X, Y, Sum) :-
Sum is X + Y.
(You could get fancy and use a constraint library for the add operation. For example, with library(clpr) you could write {Sum = X+Y} and use the same predicate for addition and for subtraction.)
This uses unification in the head to make sure that the two matrices have the same dimensions, while the maplist take care of V1 and V2 being the same length.
Or you prefer a list of lists. Then, figure out the general predicate that adds lists of lists together (see the other answer!). Now you have a weird mix where you kind of know the magnitude of one dimension in advance, but still attempt to traverse the other dimension. As your code is at the moment, it is your base case that always fails. It should be:
matrixAdd([[],[]],[[],[]],[[],[]]).
(so many lists!) and without any body. Try replacing it in your original code and see what happens.
You first need to know the following:
There is a difference between = and is/2
Check your list syntax [Head|Tail] is different from [Element1,Element2]
Unification of [X] will only work when you pass a list with exactly 1 element. Just like [[A,B],[C,D]] will only match a 2 by 2 matrix. (Note that the elements A,B,.. could be lists as well in that case)
For you hardcode solution, fixing all these issues should work, but I want to leave that to you for now.
matrixAddHardcode([[A1,A2],[A3,A4]],[[B1,B2],[B3,B4]],[[S1,S2],[S3,S4]]) :-
S1 is A1 + B1,
S2 is A2 + B2,
S3 is A3 + B3,
S4 is A4 + B4.
Solution for any X by Y
matrixAddFix([],[],[]).
matrixAddFix([L1|T1],[L2|T2],[S1|TS]) :-
listSum(L1,L2,S1),
matrixAddFix(T1,T2,TS).
listSum([],[],[]).
listSum([H1|T1],[H2|T2],[S1|TS]) :-
S1 is H1+H2,
listSum(T1,T2,TS).
I'm trying to best understand everything about this code. This is how I currently perceive what's happening:
So I can see if X > Y we swap the elements, if not we recurse down the sublist until we find an X that X > Y, if we do not, then the list is sorted.
Problems I'm having is I don't really understand the base case, bubblesort(Sorted, Sorted). I thought you would need a base case for an empty list? I would really appreciate if someone could describe a sort of step by step description of this program.
bubblesort(List,Sorted) :-
swap(List,List1),
!,
bubblesort(List1,Sorted).
bubblesort(Sorted,Sorted).
swap([X,Y|Rest],[Y,X|Rest]) :- % swaps X with Y if gt(X,Y) is true.
gt(X,Y).
swap([Z|Rest],[Z|Rest1]) :- % calls swap on sublists excluding the heads.
swap(Rest,Rest1).
gt(X,Y) :- % true if X is greater than Y.
X > Y.
I am trying to want to create a shallow predicate called say square to square each number in the list
example :
e.g. ?-square([a,[[3]],b,4,c(5),8],X).
X=[a,[[3]],b,16,c(5),64]
Trivial.
sq(X) :-
number(X) -> X2 is X*X ; X2 = X.
square(List, Squared) :-
maplist(sq, List, Squared).
But note that square([X], X2), X=2 will not have the desired effect.
I'm trying to make a function that has a list of lists, it multiplies the sum of the inner list with the outer list.
So far i can sum a list, i've made a function sumlist([1..n],X) that will return X = (result). But i cannot get another function to usefully work with that function, i've tried both is and = to no avail.
Is this what you mean?
prodsumlist([], 1).
prodsumlist([Head | Tail], Result) :-
sumlist(Head, Sum_Of_Head),
prodsumlist(Tail, ProdSum_Of_Tail),
Result is Sum_Of_Head * ProdSum_Of_Tail.
where sumlist/2 is a SWI-Prolog built-in.
Usage example:
?- prodsumlist([[1, 2], [3], [-4]], Result).
Result = -36.
The part "it multiplies the sum of the inner list with the outer list" isn't really clear, but I believe you mean that, given a list [L1,...,Ln] of lists of numbers, you want to calculate S1*..*Sn where Si is the sum of the elements in Li (for each i).
I assume the existence of plus and mult with their obvious meaning (e.g. plus(N,M,R) holds precisely when R is equal to N+M). First we need predicate sum such that sum(L,S) holds if, and only if, S is the sum of the elements of L. If L is empty, S obviously must be 0:
sum([],0).
If L is not empty but of the form [N|L2], then we have that S must be N plus the sum S2 of the elements in L2. In other words, we must have both sum(L2,S2) (to get S2 to be the sum of the elements of L2) and plus(N,S2,S). That is:
sum([N|L2],S) :- sum(L2,S2), plus(N,S2,S).
In the same way you can figure out the predicate p you are looking for. We want that p(L,R) holds if, and only if, R is the product of S1 through Sn where L=[L1,...,Ln] and sum(Li,Si) for all i. If L is empty, R must be 1:
p([],1).
If L is not empty but of the form [LL|L2], then we have that R must be the product of 'S', the sum of the elements of LL, and 'P', the product of the sums of the lists in L2. For S we have already have sum(LL,S), so this gives us the following.
p([LL|L2],R) :- sum(LL,S), p(L2,P), mult(S,P,R).
One thing I would like to add is that it is probably not such a good idea to see these predicates as functions you might be used to from imperative or functional programming. It is not the case that sumlist([1,..,n],X) returns X = (result); (result) is a value for X such that sumlist([1,...,n],X) is true. This requires a somewhat different mindset. Instead of thinking "How can I calculate X such that p(X) holds?" you must think "When does P(X) hold?" and use the answer ("Well, if q(X) or r(X)!") to make the clauses (p(X) :- q(X) and p(X) :- r(X)).
Here is a rewrite of Kaarel's answer (that's the intention anyway!) but tail-recursive.
prodsumlist(List, Result) :-
xprodsumlist(List,1,Result).
xprodsumlist([],R,R).
xprodsumlist([Head|Rest],Sofar,Result) :-
sumlist(Head, Sum_Of_Head),
NewSofar is Sofar * Sum_Of_Head,
xprodsumlist(Rest, NewSofar, Result).