Lisp - Remove instances from a list of pairs - lisp

I want to create a function in lisp that receives a number and a list of pairs and iterates through the list of pairs and removes the ones in which the result of the division between the first element of the pair, and the second element of the same pair is different from the number passed as an argument. In the end it returns a list with only the ones in which the result of the division is the same.
I have the following code so far:
(defun retira-terco(num l1)
(cond ((null l1) ())
((not (equal num (/ (car(first l1)) (cdr(first l1)))))
(retira-terco num (rest l1)))
(t (cons (first l1) (retira-terco num (rest l1))))))
When I try to run this example with a real example I get the following error:
Error: `(1)' is not of the expected type `NUMBER'
What am I doing wrong?

The problem with your code is in this line:
(/ (car(first l1)) (cdr(first l1)))
(car (first l1)) evaluates to a number, but (cdr (first l1)) evaluates to a list. You probably meant (cadr (first l1)).
That said, this code isn't that great from a lispiness point of view. You have a condition you want to filter on. Use higher order programming to express that more like this:
(defun foo (num lst)
(remove-if (lambda (item)
(equal num
(/ (car item)
(cadr item))))
lst)))

Related

>: expects a real, given (void)

I am currently struggling with creating a list that finds if all the numbers within the list are equal to each other:
(define (list-all-equal lon) (cond [(empty? lon) lon]
[(empty? (rest lon)) (first lon)]
[(empty? (rest (rest lon))) (first lon)]
[(equal? (first lon) (list-all-equal(rest lon))) (write #true)]
[(> (first lon) (list-all-equal(rest lon))) (write #false)]
[(< (first lon) (list-all-equal(rest lon))) (write #false)]
[else (list-all-equal (rest lon))]))
However, I keep on receiving the error: >: expects a real, given void. is there a way to solve the error?
write does not return a value, so when you compare to the recursive result you're going to end up comparing to "nothing".
Also, your function should return #true or #false, not list elements, and comparing list elements to the results of recursing does not make much sense.
I think you started writing code before solving the problem.
A helpful way to start is with listing the possibilities.
All elements of an empty list are equal
All elements of a singleton list are equal
If the list has at least two elements, and the first element is equal to the second element, all the elements are equal if and only if all elements in its tail are equal
Otherwise, there is at least one unequal element
Translated:
(define (list-all-equal lon)
(cond [(empty? lon) #true]
[(empty? (rest lon)) #true]
[(equal? (first lon) (second lon)) (list-all-equal (rest lon))]
[else #false]))
The problem is that you're calling write as part of the recursion, and write "returns" void, which will lead to something like this:
(> some-number (void))
Never use write to return a value from your procedures! We want to return the results, not to display them on the console. And for this case you have to implement your procedure in such a way that, if it finds a different number, it stops comparing - the result is false and we shouldn't continue. A good strategy would be to pass along the first element and compare the rest against it:
(define (list-all-equal lst)
(if (empty? lst)
#t
(list-all-equal-helper (first lst) (rest lst))))
(define (list-all-equal-helper ele lst)
(cond ((empty? lst) #t)
((not (= (first lst) ele)) #f)
(else (list-all-equal-helper ele (rest lst)))))
Or, we could use apply :)
(define (list-all-equal lst)
(apply = lst))
Either way, it works as expected:
(list-all-equal '(1 2 3))
=> #f
(list-all-equal '(1 1 1))
=> #t

Lisp function count recurring a's in list

I am trying to write a function that takes only a list as a parameter and counts the number of times the symbol a appears in the list, without counting any a's in a sublist within the list.
I am very new to Lisp so please use as basic code as possible so I could understand what it is doing, even if it is inefficient.
(defun times (l)
(setf x 'a)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x(cdr l)))))
So (times '(a b (a) c)) should return 1. However I am getting the error that with this line times is getting two arguments when it should be getting one.
There are multiple ways to implement this in Common Lisp. The example should be small enough for you to follow (test them).
Recursive implementation
Your approach is fine, except you have small errors (in addition to the other ones reported in comments):
Do not use SETF for undeclarded variables.
Do not return NIL in the base case: your function should return a number.
Also, your code coud be better formatted, and you should use longer names (lowercase l in particular is hard to read)
Here is a modified version:
(defun times (list element)
(cond
((null list) 0)
((equal (car list) element) (1+ (times (cdr list) element)))
(t (times (cdr list) element))))
Example
Let's TRACE the function:
CL-USER> (trace times)
Here is the execution trace:
CL-USER> (times '(a b c d a f a) 'a)
0: (TIMES (A B C D A F A) A)
1: (TIMES (B C D A F A) A)
2: (TIMES (C D A F A) A)
3: (TIMES (D A F A) A)
4: (TIMES (A F A) A)
5: (TIMES (F A) A)
6: (TIMES (A) A)
7: (TIMES NIL A)
7: TIMES returned 0
6: TIMES returned 1
5: TIMES returned 1
4: TIMES returned 2
3: TIMES returned 2
2: TIMES returned 2
1: TIMES returned 2
0: TIMES returned 3
3
You can see that the call stack grows for each and every element visited in the list. It is usually a bad practice, especially when the recursive function is basically implementing a loop.
Loops
Use a simple LOOP:
(defun times (list element)
(loop for value in list count (equal value element)))
Alternatively, use DOLIST:
(defun times (list element)
(let ((counter 0))
(dolist (value list counter)
(when (equal element value)
(incf counter)))))
Here above, counter is a local variable introduced by LET. It is incremented with INCF inside the loop, only WHEN the comparison holds. Finally, counter is returned from the dolist (the third parameter indicates which form to evaluate to have the result value). The return value of dolist is also the return value of the let and the whole function.
This can be rewritten also with DO:
(defun times (list element)
(do ((counter 0)) ((null list) counter)
(when (equal element (pop list))
(incf counter))))
The first list in do introduces bindings, the second list is a termination test (here we stop when the list is empty) followed by a result form (here, the counter). Inside the body of the loop, we POP elements from the input list and do the comparison, as before.
Tail-recursive implementation
If you want to keep a recursive implementation, add an accumulator and compute all the intermediate results before entering a recursive evaluation. If all results are passed as function arguments, there is no need to keep track of intermediate results at each step of the recursion, which eliminates the need to even allocate stack frames. The ability to perform tail-call elimination is not expressly required by the specification of the language, but it is typically available in most implementations.
(defun times (list element)
(labels ((recurse (list counter)
(cond
((null list) counter)
((equal (first list) element)
(recurse (rest list) (1+ counter)))
(t (recurse (rest list) counter)))))
(recurse list 0)))
Here above, recurse is a local recursive function introduced by LABELS, which accepts a counter parameter. The difference with the original recursive function is that when the list is empty, it returns the current value of counter instead of zero. Here, the result of recurse is always the same as the value returned by recursive invocations: the compiler can just rebind inputs and perform a jump instead of allocating intermediate frames.
Higher-order functions
Here are yet two other ways, based on higher-order functions.
First, the usual way to define functions with accumulators is with REDUCE (known as fold in other languages). There is no explicit mutation:
(defun times (list element)
(reduce (lambda (counter value)
(if (equal value element)
(1+ counter)
counter))
list
:initial-value 0))
The anonymous function accepts the current state of the accumulator, the current value being visited in the list, and shall compute the next state of the accumulator (the counter).
Alternatively, call MAP with a nil first argument, so that the iteration is only done for effects. The anonymous function established by the LAMBDA form closes over the local counter variable, and can increment it when comparison holds. It is similar to the previous dolist example w.r.t. incrementing the counter through side-effects, but the iteration is done implicitly with map.
(defun times (list element)
(let ((counter 0))
(map ()
(lambda (value)
(when (equal value element)
(incf counter)))
list)
counter))
Built-in
For your information, there is a built-in COUNT function:
(defun times (list element)
(count element list :test #'equal))
Here is some code which might help. It uses tail recursion and defines a helper function which is called recursively and keeps track of the number of times the symbol 'a appears with the argument count. The helper function takes two arguments, but the functino count-a takes one. Count-a calls the helper with the list l and the total number of times it has counted the symbol 'a at the beginning, which is zero to kick off the recursive calls.
(defun count-a (l)
(labels ((helper (x count)
(if (equalp 'a (car x)) (incf count))
(cond ((null x) count)
(t (helper (cdr x) count)))))
(helper l 0)))
You can also use the loop macro:
(defun count-a-with-a-loop (l)
(loop for i in l count (equalp 'a i))\
Or as Coredump points out:
(defun count-a-with-count (l)
(count 'a l :test #'equal))
Note the '# character before equal lets the Lisp interpreter know that equal is a function, known as a reader macro.
If you use a Lisp compiler (like SBCL) you might see this:
* (defun times (l)
(setf x 'a)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x(cdr l)))))
; in: DEFUN TIMES
; (TIMES X (CDR L))
;
; caught WARNING:
; The function was called with two arguments, but wants exactly one.
;
; caught WARNING:
; The function was called with two arguments, but wants exactly one.
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 3 WARNING conditions
The Lisp compiler tells you that there are three errors in your code.
Let's fix the undefined variable problem first, by introducing a local variable x:
(defun times (l)
(let ((x 'a))
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l))))))
Now, we look at the other two: you call TIMES with two arguments.
We can just remove the x argument, since it is not needed:
(defun times (l)
(let ((x 'a))
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times (cdr L))))
(t (times (cdr l))))))
It may be more useful to be able to search for more things, so we add x to the argument list and add it to the call arguments.
(defun times (x l)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l)))))
Now the function should always return a number, not NIL for an empty list:
(defun times (x l)
(cond
((null l) 0)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l)))))
Since Lisp has functions like first and rest, we can replace car and cdr:
(defun times (x l)
(cond
((null l) 0)
((equal x (first l)) (+ 1 (times x (rest l))))
(t (times x (rest l)))))

How to print the elements in odd positions in a list using an iterative function in Lisp?

I have to make a recursive function in lisp which takes a list and makes another list with only the elements on odd position in the given list.
If I have (1 2 3 4 5) I have to output (1 3 5)
I have a code here:
(defun pozpar(lst) (do(
(l lst (cddr l))
(x '() (cons x (car l))))
((null l) x)))
This outputs:
(5 3 1)
I know cons adds the elements at the beginning and I tried with append or list but nothing worked.
I think this is a way easier solution:
(defun popzar (lst)
(cond ((null lst) nil)
(t (cons (car lst)
(popzar (cdr (cdr lst)))))))
It first checks if the list is empty and if not it creates a new list with the first element and the result of calling itself again with the rest of the list except for the second element.
The easiest way is to reverse the result:
(defun pozpar (lst)
(do ((l lst (cddr l))
(x '() (cons (car l) x)))
((null l)
(nreverse x))))
(pozpar '(1 2 3 4 5))
==> (1 3 5)
Notes
This returns, not outputs the value you want.
Prepending values and reverting the result is a common Lisp coding pattern.
Since append is linear in the length of its argument, using it in a loop produces quadratic code.
I formatted the code in the standard Lisp way. If you use this style, lispers will have an easier time reading your code, and, consequently, more willing to help you.
With using loop it's very easy to get the elements in the order you processed them. It is also the most effective and the only one guaranteed to work with all length arguments:
(defun pozpar1 (lst)
(loop :for e :in lst :by #'cddr
:collect e)))
If you really want recursion I would have done it with an accumulator with a linear update reverse in the end:
(defun pozpar2 (lst)
(labels ((helper (lst acc)
(if (endp lst)
(nreverse acc)
(helper (cddr lst) (cons (car lst) acc)))))
(helper lst '())))
However a classical not tail recursive version would look like this:
(defun pozpar3 (lst)
(if (endp lst)
'()
(cons (car lst) (pozpar3 (cddr lst)))))

LISP FUNCTION - Return the count of numbers of the list that are bigger of the first element

I want to solve a lisp function that returns a NUMBER(count) of numbers which are greater than the first number in the list.The list is a linear list of numbers.
(defun foo (lst)
(cond ((null lst) 0)
(car = k)
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
My problem is that I cannot keep the first element and compare it with the others.
Let's take apart your problem:
You have a set of numbers. Really, you have a “special” first number, and then the rest of them. Specifically, you probably want only real numbers, because “less than” does not make sense in terms of complex (imaginary) numbers.
You can use first to get the first number from the list, and rest for the others.
Of these, you want to count any that are not greater than the first.
So let's start with sort of pseudocode
(defun count-numbers-greater-than-first (list)
;; split out first and rest
;; call the real count function
)
Well, we know now that we can use first and rest (also, as you used, historically car and cdr), so:
(defun count-numbers-greater-than-first (list)
(count-numbers-greater-than (first list) (rest list))
You already probably know that > is used to test whether real numbers are greater than one another.
A quick look at the CLHS reveals a nice function called count-if
(defun count-numbers-not-greater-than (reference other-numbers)
(count-if ??? other-numbers))
The ??? needs to be an object of function type, or the name of a function. We need to “curry” the reference (first number) into that function. This means we want to create a new function, that is only used for one run through the count-if, that already has “closed over” the value of reference.
If we knew that number would always be, say, 100, that function would look like this:
(defun greater-than-100 (number)
(> number 100))
That function could then get used in the count-if:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (function greater-than-100)
other-numbers))
(defun count-numbers-greater-than (reference other-numbers)
(count-if #'greater-than-100 other-numbers))
But that doesn't solve the problem of getting the reference number “curried” into the function.
Without reaching for Alexandria (I'll explain in a moment), you can use a lambda form to create a new, anonymous function right here. Since reference is available within count-numbers-not-greater-than, you can use its value within that lambda. Let's convert for 100 first:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number 100))
other-numbers))
Now we can use reference:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number reference))
other-numbers))
And, in fact, you could even merge this back into the other function, if you wanted:
(defun count-numbers-greater-than-first (list)
(count-if (lambda (number) (> number (first list)))
(rest list)))
That Alexandria thing
But, what about Alexandria? Alexandria is a collection of super-useful utility functions that's available in Quicklisp or elsewhere.
(ql:quickload "alexandria")
(use-package #:alexandria)
Of course, you'd normally use it in your own defpackage
(defpackage my-cool-program
(:use :common-lisp :alexandria))
Two of the things it provides are curry and rcurry functions. It turns out, that lambda function in there is a really common case. You have an existing function — here, > — that you want to call with the same value over and over, and also some unknown value that you want to pass in each time.
These end up looking a lot like this:
(lambda (x) (foo known x))
You can use curry to write the same thing more concisely:
(curry #'foo known)
It also work with any number of arguments. RCurry does the same, but it puts the unknown values “x” at the left, and your known values at the right.
(lambda (x) (foo x known)) = (rcurry #'foo known)
So another way to write the count-if is:
(defun count-numbers-greater-than-first (list)
(count-if (rcurry #'> (first list))
(rest list)))
* (count-numbers-greater-than-first '(10 9 8 7 11 12))
2
Your function indented correctly looks like this:
(defun foo (lst)
(cond ((null lst) 0)
(car = k) ; strange cond term
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
I have commented the second term in your cond. It is quite strange. It first evaluates the variable car (not the function #'car). If car is not nil it first evaluates the variable = (not the function #'=) and since it is not the last consequent expression in the cond term it throws that away and returns the last which is k.
Secondly you write that you say you use the first element as comparison, however you call it k in your function but it is not defined anywhere. You need to do something before you do the recursion and thus you cannot let the actual function do the recursion since it will take the first element each time. Here is where labels can be used:
;; didn't call it foo since it's not very descriptive
(defun count-larger-than-first (list)
(let ((first (car list)))
(labels ((helper (list)
(cond ((null list) 0)
((> (car list) first)
(1+ (helper (cdr list))))
(t (helper (cdr list))))))
(helper (cdr list)))))
Of course. Since you now have the possibility to add more arguments I would have added an accumulator:
(defun count-larger-than-first (list)
(let ((first (car list)))
(labels ((helper (list acc)
(cond ((null list) acc)
((> (car list) first)
(helper (cdr list) (1+ acc)))
(t (helper (cdr list) acc)))))
(helper (cdr list) 0))))
And of course recursion might blow the stack so you should really write it without in Common Lisp:
(defun count-larger-than-first (list)
(let ((first (car list)))
(loop :for element :in (cdr list)
:counting (> element first))))
There are higher order functions that count too which might be more suitable:
(defun count-larger-than-first (list)
(let ((first (car list)))
(count-if (lambda (element) (> element first))
(cdr list))))

too many arguments given a function

I'm having an error that i don't understand why...
"too many arguments given to ULTIMO"
The purpose of this function is to return the last element of a list
(defun ultimo (lst)
(cond ((= 1 (length lst))
(first lst)))
(t
(ultimo (rest lst))))
There is a problem with the parentheses. The function should be defined in this way:
(defun ultimo (lst)
(cond ((= 1 (length lst)) (first lst))
(t (ultimo (rest lst)))))
Note that by using an editor that can format correctly lisp syntax this kind of errors happens very rarely.
However, your function does not manage correctly the empty list case (it enters an endless loop). A correct version could be:
(defun ultimo (lst)
(cond ((null list) nil)
((null (rest list)) (first lst))
(t (ultimo (rest lst))))
As a side note, consider that using the length function in a context like this is not recommended, since it is executed by visiting the entire list,