Check if element is in a tree - lisp

I need to write a function in Lisp that checks if an element N is in a tree TREE.
(defun TREE-CONTAINS (N TREE)
(cond ((equal TREE nil) nil)
((listp (CAR TREE)) (or (TREE-CONTAINS(N (CAR TREE)))
(TREE-CONTAINS(N (CDR TREE)))))
(t (cond ((equal N (CAR TREE)) t)
(t TREE-CONTAINS(N (CDR TREE)))))
)
)
For example, (TREE-CONTAINS (1 ((1 2 3) 4 5))) will return true. But I keep getting an error that says "Undefined function N called with arguments ((2 3))" when I test my code with this example: (TREE-CONTAINS 2 '(1 2 3)). Of course N is supposed to be 1 here but I don't know why it thinks N is a function. Any idea?

In the call to tree-contains, or any lisp function, you should not include parentheses around the arguments. It's (function-name arg1 arg2), not (function-name (arg1 arg2)).
So for a start, remove the parentheses around the arguments to the call (tree-contains(n (car tree))) like so: (tree-contains n (car tree)). Similarly for the next call to tree-contains in that or clause. Besides, the last condition: (t TREE-CONTAINS(N (CDR TREE))) should be called like this: (t (tree-contains n (cdr tree))).

Related

list as function argument in Lisp

i have the following code:
(defun TREE-CONTAINS (N TREE)
(cond (( = (car TREE) nil) nil)
(( = (car TREE) N) t)
(t TREE-CONTAINS (N (cdr TREE)))
)
)
which accepts a number N and a list TREE and checks to see if N exists in the list TREE. pretty simple, but for some reason i keep getting this error when i call my function
(TREE-CONTAINS 3 '((1 2 3) 7 8))
*** - +: (1 2 3) is not a number
is there an issue with the code? i'm very new to Lisp so maybe i'm just not seeing something very obvious.. thanks in advance!
Syntax errors
Your code contains several syntax errors that are flagged as compiler warnings:
CL-USER> (defun TREE-CONTAINS (N TREE)
(cond (( = (car TREE) nil) nil)
(( = (car TREE) N) t)
(t TREE-CONTAINS (N (cdr TREE)))
)
)
;Compiler warnings :
; In TREE-CONTAINS: Undeclared free variable TREE-CONTAINS
; In TREE-CONTAINS: Undefined function N
TREE-CONTAINS
The reason is that parentheses in Common Lisp have a meaning different from that of other programming languages: they are not used to specify the order of application of the operators (like in 3 * (2 + 4) which is different from 3 * 2 + 4), but are integral part of the syntax to specify the different parts of a “statement”, like in cond or in function application (like (function-name arg1 arg2 ... argn)). So the syntax error in this case is in the last line, in which you should call the function TREE-CONTAINS with arguments N and (cdr TREE) as:
CL-USER> (defun TREE-CONTAINS (N TREE)
(cond (( = (car TREE) nil) nil)
(( = (car TREE) N) t)
(t (TREE-CONTAINS N (cdr TREE)))
)
)
TREE-CONTAINS
Semantic errors
If you try this function, however, you will find an error:
CL-USER> (TREE-CONTAINS 2 '(1 2 3))
The value NIL is not of the expected type NUMBER.
The reason is that you have used = to compare a number ((car TREE)) with the value nil, while = can be used only to compare numbers. Use eq or eql instead for the general case:
CL-USER> (defun TREE-CONTAINS (N TREE)
(cond (( eql (car TREE) nil) nil)
(( = (car TREE) N) t)
(t (TREE-CONTAINS N (cdr TREE)))
)
)
TREE-CONTAINS
CL-USER> (TREE-CONTAINS 2 '(1 2 3))
T
There is also another problem: you should check if the list is empty, not if the first element is nil. In other words, the first condition should be:
(cond ((eq TREE nil) nil)
or better:
(cond ((null TREE) nil)
Stylistic notes
A list is a particular case of tree: if you use the term tree the program should be more complex, taking into account cases in which the elements can be sublists.
Use lowercase identifier, since everything is translated to upper-case
Put the close parentheses at the end of the expression, not on a new line.
So your function could be something like:
(defun list-contains (n list)
(cond ((null list) nil)
((= (car list) n) t)
(t (list-contains n (cdr list)))))
Check membership for a tree and not a list
If, on the other hand, you want to check for a generic tree, i.e. a list which can contain sublists, like in (tree-contains 3 '((1 2 3) 7 8)), in your recursion you should consider tha case in which an element of the list is itself a list, and then perform a double recursion. Here is a possible solution:
CL-USER> (list-contains 2 '(1 (2 3) 4))
The value (2 3) is not of the expected type NUMBER.
CL-USER> (defun tree-contains (n tree)
(cond ((null tree) nil)
((listp (car tree)) (or (tree-contains n (car tree))
(tree-contains n (cdr tree))))
((= (car tree) n) t)
(t (tree-contains n (cdr tree)))))
TREE-CONTAINS
CL-USER> (tree-contains 2 '(1 (2 3) 4))
T
In addition to the accepted answer, here is an alternative way of writing the same predicate, without cond:
(defun list-contains-p (number list)
(and (consp list)
(or (= number (first list))
(list-contains-p number (rest list)))))

LISP recursive pairing?

I'm new to LISP and I'm trying to create a recursive function that pairs the elements within a list. I'm stuck on the last part of my function with adding in the recursion.
(defun pairup (L)
(cond((null L) nil))
(list (cons (car L) (cadr L)(pairup(cdr L)))))
I know that (pairup(cdr L)))))) will show an error because its a third argument going into cons. Not sure how to add in the function again =/
INPUT: (pairup'(1 2 3 4))
OUTPUT: ((1 2) (3 4))
Here is the function:
(defun pairup (l)
(cond ((null l) nil)
((null (cdr l)) (list l))
(t (cons (list (car l) (cadr l))
(pairup (cddr l))))))
(pairup '(1 2 3 4)) ; produces ((1 2) (3 4))
(pairup '(1 2 3)) ; produces ((1 2) (3))
Note that the second branch of the cond is to terminate the recursion when only one element is left, and this is necessary if the initial list has an odd number of elements. The syntax of the cond requires that the first form of a branch be always a condition, and in the last branch the condition is t to catch all the other cases.

List without nil in result Lisp

I have to delete all occurences of an element in a list from all levels.
My code is:
(defun sterge(e l)
(cond
((and (atom l) (equal e l)) nil)
((atom l) (list l))
(t (append (apply #'list (mapcar #' (lambda (l) (sterge e l)) l))))
)
)
(defun sterg(e l)
(car (sterge e l))
)
When I give:
(sterg 1 '(1 2 1 ( 1 2 1( 1 (1) (1)) (1) 3) (1)(2)))
it shows me the output:
((2 (2 (NIL NIL) NIL 3) NIL (2)))
How to delete that nil?? Thank you.
Instead of returning nil, consider returning sterge applied to the rest of the entity l. mapcar is not the best way to approach this problem; a recursive function is better (unless the assignment specifies using mapcar, of course.)
Hint: Treat l as if it were a list and test (car l), e.g., (atom (car l)), apply sterge to (cdr l).

Learning Lisp. Can't seem to get a value from one function and use it within another

I'm trying to find the maximum number within a list, then do something with it:
(defun maxList (l)
(if (= (length l) 1)
(first l)
(if (> (first l) (maxList (rest l)))
(first l)
(maxList (rest l))
);if
);if
);defun
(defun try-let (l)
(let (a (maxList l))
(print a)
);let
);defun
However it prints null, yet maxList works. What am I doing wrong ?
You're missing a pair of parentheses:
(let ((a (maxList l)))
This is because let takes a list of bindings as in
(let ((a 1) (b 2) (c 'foo))
expr)
so in this case you have to pass a one-element list containing the binding (a (maxList l))
(defun maxList (l)
(if (= (length l) 1)
Calling LENGTH is not a good idea. It traverses the whole list.
(first l)
(if (> (first l) (maxList (rest l)))
(first l)
(maxList (rest l)))))
Above calls MAXLIST twice. Maybe here a LET is useful? How about the function MAX?
If you compile your function, a Common Lisp system will complain.
CL-USER 35 > (defun try-let (l)
(let (a (maxList l))
(print a)))
TRY-LET
CL-USER 36 > (compile 'try-let)
;;;*** Warning in TRY-LET: MAXLIST is bound but not referenced
This shows that the Lisp compiler thinks MAXLIST is a variable. Something is wrong. Next look up the syntax of LET.
See Special Operator LET, LET*
let ({var | (var [init-form])}*) declaration* form* => result*
Which says that it is a list of variables or a list of (variable initform). So you can see that you have missed to make it a list. You have just written one binding.

LISP - removing an element from a list with nested lists

I need to remove an element from a list which contain inner lists inside. The predefined element should be removed from every inner list too.
I have started working with the following code:
(SETQ L2 '(a b ( a 2 b) c 1 2 (D b (a s 4 2) c 1 2 a) a )) ; defined my list
; Created a function for element removing
(defun elimina (x l &optional l0)
(cond (( null l)(reverse l0))
((eq x (car l))(elimina x (cdr l) l0))
(T (elimina x (cdr l) (cons (car l) l0))))
)
(ELIMINA 'a L2)
But unfortunately it removes only elements outside the nested lists.
I have tried to create an additional function which will remove the element from the inner lists.
(defun elimina-all (x l)
(cond ((LISTP (CAR L))(reverse l)(elimina x (car l)))
(T (elimina-all x (CDR L)))
)
)
but still unsuccessfully.
Can you please help me to work it out?
Thank you in advance.
First of all, I'd suggest you read this book, at least, this page, it explains (and also gives very good examples!) of how to traverse a tree, but most importantly, of how to combine functions to leverage more complex tasks from more simple tasks.
;; Note that this function is very similar to the built-in
;; `remove-if' function. Normally, you won't write this yourself
(defun remove-if-tree (tree predicate)
(cond
((null tree) nil)
((funcall predicate (car tree))
(remove-if-tree (cdr tree) predicate))
((listp (car tree))
(cons (remove-if-tree (car tree) predicate)
(remove-if-tree (cdr tree) predicate)))
(t (cons (car tree)
(remove-if-tree (cdr tree) predicate)))))
;; Note that the case of the symbol names doesn't matter
;; with the default settings of the reader table. I.e. `D' and `d'
;; are the same symbol, both uppercase.
;; Either use \ (backslash) or || (pipes
;; around the symbol name to preserve the case. Eg. \d is the
;; lowercase `d'. Similarly, |d| is a lowercase `d'.
(format t "result: ~s~&"
(remove-if-tree
'(a b (a 2 b) c 1 2 (D b (a s 4 2) c 1 2 a) a)
#'(lambda (x) (or (equal 1 x) (equal x 'a)))))
Here's a short example of one way to approaching the problem. Read the comments.
Maybe like this:
(defun elimina (x l &optional l0)
(cond ((null l) (reverse l0))
((eq x (car l)) (elimina x (cdr l) l0))
(T (elimina x (cdr l) (cons (if (not (atom (car l)))
(elimina x (car l))
(car l))
l0)))))
I was looking for the same answer as you and, unfortunately, I couldn't completely understand the answers above so I just worked on it and finally I got a really simple function in Lisp that does exactly what you want.
(defun remove (a l)
(cond
((null l) ())
((listp (car l))(cons (remove a (car l))(remove a (cdr l))))
((eq (car l) a) (remove a (cdr l)))
(t (cons (car l) (remove a (cdr l))))
)
)
The function begins with two simple cases, which are: 'list is null' and 'first element is a list'. Following this you will "magically" get the car of the list and the cdr of the list without the given element. To fixed that up to be the answer for the whole list you just have to put them together using cons.