Output not as expected in Racket - output

I ran this code and I don't understand how the output is 2? As far as I'm concerned the output should always be 1?
Code:
(define (count p l)
(if (empty? l)
0
(if (p (first l))
(+l (count p (rest l)))
(count p (rest l)))))
(define (ident x)
x)
(count ident '(#true #true #false))

Your function count counts the number of elements in the list that satisfy the predicate p. Since you are using ident as the predicate, we have that (ident #true) = #true and (ident #false) = #false does not. This means that you have two values in your example list that are counted. This matches the result 2.

First, you have used the number 1 instead of the letter l for the list, so your code will not even run the way it is. After fixing that to:
(define (count p l)
(if (empty? l)
0
(if (p (first l))
(+ 1 (count p (rest l)))
(count p (rest l)))))
you should get an output of 2, as you noticed, because the procedure is essentially counting up by one whenever (p (first l)) evaluates to true. And it holds that:
> (if #true 1 0)
1
> (if #false 1 0)
0
so for the list '(#true #true #false), the procedure will count up twice, hence the result being 2.

Related

Function to count number of 0 in given arguments in lisp

I want to create a function in LISP
to count the number of 0 in given arguments
Ex
(count_number_of_0 '(1 0 5 9 0 0 0 7 1 0) )
Output : 5
Here is an implementation in Racket, which is a lisp-family language. It would be quite easy to translate into Common Lisp (but a little more verbose in CL):
(define make-counter
(λ (v same?)
(λ (l)
((λ (c)
(c c 0 l))
(λ (c a t)
(if (null? t)
a
(c c (if (same? (first t) v) (+ a 1) a) (rest t))))))))
(define count-zeros
(make-counter 0 =))
And now
> (count-zeros '(1 2 0 3 4 0))
2
one way is:
(defun count-number-of-0 (lst &optional (cnt 0)) ;counter starts at zero
(if lst
(if (and (numberp (car lst)) ;better verify that element is a number
(= 0 (car lst)))
(progn
(setq cnt (+ cnt 1))
(count-number-of-0 (cdr lst) cnt))
(count-number-of-0 (cdr lst) cnt))
cnt)) ;return counter
This should work in all implementations of common-lisp.

Lisp Product Function

I'm just starting out on lisp. I'm trying to make a product function written in Lisp. The function should take in an arbitrary parameter x, and returns the product of all numerical values contained in x. It should produce the following:
>(product 'x) -> 1
>(product '(x 5)) -> 5
>(product '((2 2)3)) -> 12
>(product '((a 3)(2 1))) -> 6
I was able to do the following:
(defun product (x)
"This function takes in an arbitrary parameter x, and returns the product of all numeric values contained within x."
(cond
((consp x) (* (car x)(product (cadr x))))
((numberp x) x)
(t 1)
)
)
This handles the cases like
(product '(2 5))-> 10
(product 'x) -> 1
But not for ones like:
>(product '(x 5)) -> 5
>(product '((2 2)3)) -> 12
I'm not sure where to go from here.
The first clause of your cond expression reads as follows:
If x is a cons cell, multiply its first element (assumed to be a number) with the result of calling product on its second element (or NIL).
Both (product '(x 5)) and (product '((2 2) 3)) fail because the first element is not a number. You should multiply by (product (car x)) instead of (car x), in order to convert your arbitrary terms into numbers.
Note also that recursing on cadr is not enough to iterate over all elements of your input list. You probably intended to use cdr.

Common Lisp - Function that builds, from a list of numbers, the list of more, smaller or equal to a given number

I having trouble with this function,
I would like a function which
returns a list of number inferior for a given a number.
What I did so far,
(defun inf (n l)
(cond
((not l) 0)
((>= n (car l))(cons n (inf n(cdr l))))
(cons (car l) (inf n (cdr l))) ))
But it keeps returns
(inf 12 '(12 5 3))
(12 12 10)
Instead of :
(inf 12 '(12 5 3 53 45))
(12 5 3)
What did I miss ?
First of all, the function you posted does not behave the way you claim.
The 1st invocation returns (12 12 12 . 0) (because you return 0 instead of nil in the 1st cond clause)
and the second invocation raises an exception
COND: variable CONS has no value
because you got cond syntax wrong.
Second, the question summary, question text, and the attempted
implementation, specify three different problems.
Here is a fix for your code (I replaced
car and cdr with
first and
rest for pedagogical reasons):
(defun inf (n l)
(cond
((not l) ()) ; return empty list
((>= n (first l))
(cons n (inf n (rest l))))
(t
(cons (first l) (inf n (rest l))))))
If this is, in fact, what you want, you can implement in a more
idiomatic way:
(defun inf-1 (n l)
(and l (cons (max n (first l)) (inf-1 n (rest l)))))
or even
(defun inf-2 (n l)
(mapcar (lambda (x) (max n x)) l))
If you actually want the list of numbers less than the given one, you
can use remove:
(remove 12 '(12 5 3 100) :test #'<=)
==> (5 3)
A not-so-obvious way to solve the same problem using Common Lisp's existing functions is to pass a comparison operator to REMOVE.
(remove 10 '(0 3 5 11 22 10 22 3 2) :test #'<)
The above removes all elements "equal" to 10 according to #'<, which are thus all elements u such that (< 10 u) holds. In other words, all elements strictly above 10:
(0 3 5 10 3 2)
It turns out that there is an example of this in the section linked above:
(remove 3 '(1 2 4 1 3 4 5) :test #'>) => (4 3 4 5)
Edit: since this is now the accepted answer, note also that this approach is probably hard to read, be careful when using it (add a comment, etc.).

Higher-order functions

given,
(define (reduce f id lis)
(if (null? lis) id
(f (car lis) (reduce f id (cdr lis)))))
The length of a list can be defined in terms of reduce (as opposed to
using a recursive definition from scratch) as
(define (mylength lis) (reduce (lambda (x n) (+ 1 n)) 0 lis)).
Define the list function mymap (similar to map) that takes a unary function uf and a list lis in terms of reduce, that is, by determining the corresponding f and id in
(mymap uf lis) = (reduce f id lis),
Recall that mymap returns a list resulting from calling the function on every element in the input list such as (mymap (lambda(x) (* 2 x)) '(1 2 3)) = (2 4 6).
A little Explanation to how this has been done would be helpful, rather than a blatant answer. Thank You.
we have
(mymap uf lis) = (reduce f id lis) =
= (if (null? lis) id
(f (car lis) (reduce f id (cdr lis))))
which must be equal to
= (if null? lis) '()
(cons (uf (car lis)) (mymap uf (cdr lis))))
matching the corresponding entities, we get
id == '()
and, since (mymap uf lis) = (reduce f id lis), it is also (mymap uf (cdr lis)) = (reduce f id (cdr lis)), so we have
(f x y) = (cons (uf x) y)
Thus, we define
(define (mymap uf xs) ; multiple `x`-es :)
(reduce (lambda (x r)
(cons .... r))
'()
xs ))
your reduce is a right fold: its combining function receives an element x of the argument list xs, and the recursive result of working on the rest of list, as r.
r has all the elements of the rest of xs, which were already mapped through uf. All that's left to do to combine the given element x with this recursive result r, is to cons the (uf x) onto r.
It should pose no problem now to complete the definition by writing the actual code in place of the dots .... there.

Multiplying 2 lists in Lisp

I have a function that takes 2 lists as input and I would like to make it so that everything in the first list, is multiplied with everything in the second list, and then the sum is calculated.
Here's my function so far:
(defun multiply(a b)
(if (eq a nil)
0
(progn
(* (car a) (car b))
(multiply (car a) (cdr b)))
))
Currently all I'm trying to get it to do is take the first number from the first list, and multiply one by with everything in the second list. However I get this error from when the function is re-called within the function:
(This is what I inputted, '(1 2 3) and '(4 5 6))
The value 1 is not of type list.
(MULTIPLY 1 '(5 6))
Any help would be much appreciated.
Is loop acceptable?
Case 1
If the result should be 90 as in
(+ (* 1 4) (* 1 5) (* 1 6) (* 2 4) (* 2 5) (* 2 6) (* 3 4) (* 3 5) (* 3 6))
then you could do
(defun multiply (a b)
(loop for i in a
sum (loop for j in b
sum (* i j))))
Case 2
If the result is supposed to be 32 as in
(+ (* 1 4) (* 2 5) (* 3 6))
then it would be
(defun multiply (a b)
(loop
for i in a
for j in b
sum (* i j)))
If you want to multiply two lists per element, you should just be able to use mapcar:
(mapcar #'* '(3 4 5) '(4 5 6))
As to the error in your existing function, this line should be:
...
(multiply (cdr a) (cdr b)))
...
What you describe sounds like the dot product:
(defun dot (l1 l2)
(reduce #'+ (mapcar #'* l1 l2)))
The above solution is nice because it is purely functional, but, alas, it creates an unnecessary intermediate list. Of course, a Sufficiently Smart Compiler should be able to eliminate that, but, practically speaking, you are better off using loop:
(defun dot (l1 l2)
(loop for x in l1 and y in l2 sum (* x y)))
Note also that using lists to represent mathematical vectors is not a very good idea, use vectors instead.
I would modify multiply as
(defun multiply(a b)
(if (eq a nil)
0
(+
(* (car a) (car b))
(multiply (cdr a) (cdr b)))))
When you call
(multiply '(1 2 3) '(4 5 6))
it will return the sum
32
(define (*2Ls L1 L2)
(apply map * (list L1 L2)))