Prolog: square numbers in a list - list

Ho do I square numbers in a list in prolog?
The list can contain numbers, atoms and lists.
for example: [a,b,2,3,4,[3],[c,d,9]] and the answer should be [a,b,4,9,16,[3],[c,d,9]].
As we see in the answer it should be a shallow squaring of the values in the list.
2->4
3->9
4->16
What I have tried so far,
square([],X).
square([A|B],X):-number(A), A is A*A, square(B,X).
X will contain squared values. Base case is when empty list is received. I check if head (A) is a number then I go ahead square the number and change A to A * A. Then go ahead and call the square function for remaining part B.
Please suggest where I am doing wrong.
EDIT: Correct answer as follows. By aBathologist. Please read his comment for detailed explanation.
squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
number(L),
SqrdL is L * L,
squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
\+number(L),
squared_members(Ls, SqrdLs).
And
squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
( number(L)
-> M is L * L, squared_members(Ls, Ms)
; M = L, squared_members(Ls, Ms)
).

We're defining a predicate which describes the relationship between one list, A, and another list, B: B should have all the same elements as A, except that any number in A should be squared in B.
Where you've gone wrong:
Your ground condition, square([],X), says that when A is empty, then B is anything (so, for instance, even something like square([], 15) is true). But this doesn't capture the meaning we're after, since the second argument should be a list with the same number of members as the first. That is, when the first list is empty then the second list should be empty.
The same problem occurs with your recursive rule, since, at each iteration, an undetermined variable is passed along, and there is never anything said about the relationship between the first list and the second.
This rule will only succeed if the first element of alist is a number. In the case where the first element is, e.g., a (like in your example), number(a) will be false. Since there are no additional rules for the predicate, it will simply be false unless every member of the first list is a number.
Variables in Prolog must always have the same, consistent value throughout the context in which they appear. They function like variables in arithmetic formula. The formula a + b - b = a is true for any values of a and b but *only if a and b are each assigned one, consistent value throughout the equation. The same is true in Prolog statements of the form <variable> is <expression>. What you've written says a = a * a which cannot be the case.
*What you're definition says is, roughly, this: The list B is a squared version of the list A if A is an empty list and B is anything OR if the first element of A is a number, and that number is equal to itself squared, and B is a squared version of the rest of A.
Here's one possible solution:
squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
number(L),
SqrdL is L * L,
squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
\+number(L),
squared_members(Ls, SqrdLs).
Notice that this definition is able to establish a meaningful relationship between the two lists by having them either share variables, or contain elements related by a chain of relations between variables (i.e., SqrdL is related to L by virtue of being L * L). This definition has one more clause then yours, which enables it to take account of the members of a list which are not numbers: those are added to the second list unaltered.
An alternative definition, using If-Then-Else notation for cleaner expression, would be the following:
squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
( number(L)
-> M is L * L, squared_members(Ls, Ms)
; M = L, squared_members(Ls, Ms)
).

Related

Using a single clause compute whether the sum of any three members of a list is equal to given value

We are not supposed to use any of the functions other than the ones listed below:
A single clause must be defined (no more).
+
,
;
.
!
:-
is
Lists
Head and tail syntax for list types
Variables
For example sumlists([1,2,3,5,7],11) then the program execution should print TRUE. Because 1+3+7 (any three)=11 (given N value).
Ideally, we either get an element or don't, as we go along the input list; and we stop either on having reached the needed sum, or having surpassed it, or when the list has been exhausted.
But we can only have one clause one predicate here, and only use certain primitives, so instead we sneakily use + both symbolically, to gather the information for summation, and as an arithmetic operation itself:
sumlists(L, N) :-
N = X+A+B+C, X is A+B+C, !
; L = [H|T], sumlists(T, N+H)
; L = [H|T], sumlists(T, N).

Prolog - How to get the sum of a list's elements?

I'm very new to prolog and I am trying to write a little program that, given a list, returns the sum of the list's elements. Following all the examples I've seen led me to a solution that looks like this:
addup([],0).
addup([FirstNumber | RestOfList], Total) :-
addup(RestOfList, TotalOfRest),
Total is FirstNumber + TotalOfRest.
But when I test that solution with these values:
?- addup([1,2,3,4],0).
I just get garbage values from it like _34521.
Then I tried a second solution that looks like this:
sum([], 0).
sum([H|T], N):-
X is H+N,
sum(T, X).
This one is able to add up the numbers correctly, but it is unable to pass the final value of X, which is the true answer, into N. So for the test case:
?- sum([1,2,3,4], 0).
I get an answer of 6, the final value of N, and the second-to-last value of X, instead of 10, the final value of X. Any help and/or explanations of why neither of these solutions work would be greatly appreciated. Thanks.
Firstly, the sum of an empty list is 0 - this is the base case, which you already had.
Secondly, the sum N of an element H and a list T is the sum of the list T added to H. Prolog operates on unification, so this says that N is unified with the sum of H and T, where the sum of T is unified with X using sum(T,X).
sum([], 0).
sum([H|T], N):-
sum(T, X),
N is X + H.
This gives:
?- sum([1,2,3,4],N).
N = 10.
In your original question, ?- sum([1,2,3,4], 0). actually says "this is true if the sum of the list [1,2,3,4] is 0" - you need to pass a variable as the second argument to sum to be unified with the answer.
Further information:
_34521 is a representation of an unbound variable - this says that there is a variable, but that it has not yet been unified with a value.
Secondary consideration:
For a suitably long list, the implementation above will run out of stack space, as each frame of the recursion must be stored, so that the addition can happen from the bottom up. In order to prevent a stack error, we can use a tail-recursive accumulator like so:
sum(L, N):-
sum(L, 0, N).
sum([],N,N).
sum([H|T],A,N) :-
A1 is A + H,
sum(T,A1,N).
... which retains the signature of the original method, wrapping sum/3. As there is no choice-point in the body of the rule (given that A + H is always the same for a given A and H, and the list is either empty or not), Prolog will discard each frame as it leaves scope (as there is nothing more to be done with it) and, on completion, will return to the original caller.
Simplified stack for sum([1,2,3],N) in each instance:
non-tail-recursive:
rest-of-stack
rest-of-stack,sum([1|[2,3]],_1001)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],_1002)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],_1002),sum([3|[]],_1003)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],_1002),sum([3|[]],_1003),sum([],0)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],_1002),sum([3|[]],3)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],5)
rest-of-stack,sum([1|[2,3]],6)
rest-of-stack
tail-recursive:
rest-of-stack
rest-of-stack,sum([1,2,3],_1001)
rest-of-stack,sum([1|[2,3]],0,_1001)
rest-of-stack,sum([2|[3]],1,_1001)
rest-of-stack,sum([3|[]],3,_1001)
rest-of-stack,sum([],6,6)
rest-of-stack
Note that the tail-recursive stack has a limited depth for any length of list (dependent on what is calling it), where the non-tail-recursive stack goes to a depth directly proportional to the length of the list.
Thus, a call such as N is 10^7,length(L,N),maplist(=(1),L),sum(L,N). (as raised by #false) will likely fail without tail-recursion, and likely succeed with it.

How do I return a specific list in Prolog?

I've written a small Prolog program that's supposed to check a list and see whether the head Ha is greater than K, if it is, it is supposed to append it to a list R and after checking the whole list give back R which then would consist of bigger than K integers.
This code returns R = [].
teilliste_grK([],_,_).
teilliste_grK([Ha|Ta], K, R) :-
Ha =< K,
teilliste_grK(Ta,K,R).
teilliste_grK([Ha|Ta], K, R) :-
Ha > K,
append(R, [Ha], C),
teilliste_grK(Ta, K, C).
Any help?
you should write out how do you want to call this predicate with some sample data, and what you're expecting to get back from it. this is important. :)
okay, I'll do it: teilliste_grK([1,4,2,5,3,6],3,X) should succeed, instantiating X to [4,5,6], correct? Now try to see which of the clauses does it match with.
So it matches with the second, 1 is indeed =< 3, and the last line says, continue without the head element (that was smaller than the given K), and whatever R we get from there, is our R as well – R is R after all.
Good. So when we come to 4 next, what happens? The 2nd clause matches but is then rejected with 4 =< 2. Good. On to the third clause.
Again it matches, and the inequality holds, but then you do something strange. You first say that C is one element longer than R, and that C you get from the shorter list - the tail Ta of your input. Whatever you set your R in the final clause (the first one), this just can't be.
You want your C to be shorter than R, which is to start with the same head Ha which has just passed the test, so the arguments just need to be put in a different order:
append([Ha], C, R),
(you can write this shorter and simpler though, without any call to append – what is it?).
Now what about that final (3rd, i.e. []) clause? If you call teilliste_grK([],3,X), what should X be?

Prolog Calling predicates within predicates correctly

I have two predicates in Prolog, the first one does return a correct dot product of two lists(vectors w/e) ... the second is when you take a list times a list of lists(matrix) which will return a list. The second one fails when I try to pass anything such as ([1,2],[[3,4],[5,6],[7,8]], X). Anyone well versed in Prolog see my mistake? I am kinda stuck since tracing and prolog itself just returns a fail all the time.
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix(_,[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
N is getDotProd(List, MH, _),
vecTimesMatrix(List, Mtail, N).
Updated Code thus far now:
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Your remaining problem is in your vecTimesMatrix predicate:
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Issues:
In the second clause, the first argument is given as [List] which would imply a list of a single element (List). Subsequent calls to getDotProd and vecTimesMatrix in the clause indicate that this should simply be List.
In the second clause, the third argument is shown simply as a list of one argument: [N]. So the third argument never "builds" a list. Additionally, the recursive call to vecTimesMatrix has N as its third argument, and that argument had already been instantiated by the prior query to getDotProd as the dot product of the vector List and the vectory MH. Logically, the recursive call should be saying that the vector product of List with Mtail is the tail of the final product.
The base case assumes that the first argument reduces to [], but this is not so. List always remains as-is throughout the recursive process. So instead of [] you should have _ (it will keep its value, but you don't care about it in the base case).
The base case has as a second argument [[]], but that's not the correct form for an empty list. That's actually a list consisting of one element, that element being the empty list. In reality, even though the second argument is a "list of lists", the empty list is still [].
Putting it all together (and renaming predicates per de facto conventions using underscores rather than camel case):
get_dot_prod([], [], 0.0). % Dot product of empty vectors is 0.0
% (Dot prod of vectors of unequal length
% is not defined and will fail)
get_dot_prod([H1|T1], [H2|T2], N) :- % N is dot product of [H1|T1] [H2|T2] if...
get_dot_prod(T1, T2, N1), % N1 is dot product of T1 T2, and
N is N1 + (H1 * H2). % N is N1 + (H1*H2) [evaluated]
vec_times_matrix(_, [], []). % Product of any vector with
% empty matrix is empty
vec_times_matrix(List, [MH|Mtail], [N|Ntail]):-
% [N|Ntail] is List x [MH|Mtail] if...
get_dot_prod(List, MH, N), % N is dot product of List and MH, and
vec_times_matrix(List, Mtail, Ntail). % Ntail is List x Mtail
This will yield:
| ?- vec_times_matrix([1,2],[[1,0],[0,1]], M).
M = [1.0,2.0] ? a
no
| ?- vec_times_matrix([1,2],[[1,0],[0,1],[1,1]], M).
M = [1.0,2.0,3.0] ? a
(1 ms) no
I added the comments in the code above to illustrate, in a simple way, how to think of the prolog predicate logic, which aids in defining them. As was pointed out already, the prolog "predicate" doesn't act as a "function". It describes a logical relation between entities which will either succeed or fail.
Once you learn to think how prolog thinks (relationally), you'll find it more enjoyable. :)
There are several problems in your code. First, you define both getDotProd/4 and getDotProd/3 predicates. The first one is a typo. I.e. you base case for the getDotProd/3 predicate have a duplicated argument and it should be:
getDotProd([], [], 0).
Second, in the second predicate, vecTimesMatrix/3, you have a goal, a call to the built-in predicate is/2, that will cause an exception:
N is getDotProd(List, MH, _)
You cannot define your own functions on standard Prolog. You need to replace that goal with:
getDotProd(List, MH, N)
There are other problems but this should help you progress.

Prolog length of a list

How can I calculate the length of a list
?- size_sub([[b,a,g], [9,3,7,4], [6]], X).
X = [3, 4, 1].
?- size_sub([[c,g,e,w], [7]], X).
X = [4, 1].
?- size_sub([], X).
X = [].
Ok you need to start with the base case which is the last answer
so size_sub([],X). is true if X=[] so first you write that as a rule.
size_sub([],[]).
Then you need to do the inductive step a list that is one longer than the previous. I am going to assume that you have a size/2 function for determining the size of a single list (if not please comment).
So the inductive step is going to operate on the length of the first parameter so N->N+1. We would represent this by striping off the head of the list syntax will be [H|T] now the second parameter (your answer) is going to be the length of H with the result of calling size_sub on T. As we cannot specify rules in the parameters in the header we will use N to represent the length of H and T2 to represent the result of size_sub on T.
So the first part of the rule becomes size_sub([H|T],[N|T2]):-
now we follow it with the predicates that will assert the values for N and T2.
size(H,N),
size_sub(T,T2).
putting that all together you get
size_sub([],[]).
size_sub([H|T],[N|T2]):-
size(H,N),
size_sub(T,T2).
size/2 is a far simpler case and following the same process of base + inductive you should be able to create the rules for it. Please comment if you need further help.
** EDIT - Request for size/2 definition **
To define size/2
Start with the base case, the empty list has a size of 0.
size([],0).
Now the inductive step. The size of list of length(N+1) is the size of a list of length(N). So lets define our list as [_|T] I've defined the list using _ to represent the head because we never use it so we can just use the anonymous variable. Lets use N to represent the length of T, and M to be N+1.
so
size([_|T],M):-
now lets define N
size(T,N),
and finally assert that M is equal to N + 1
M is N+1.
so putting everything together
size([],0).
size([_|T],N):-
size(T,M),
N is M+1.
size_sub([],[]).
size_sub([H|T],[N|T2]):-
size(H,N),
size_sub(T,T2).
To map length/2 over a list of lists, we can use the meta-predicate maplist/3 like this:
size_sub(Xss,Ls):-
maplist(length,Xss,Ls).