list as function argument in Lisp - 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)))))

Related

Common LISP: Make Your Own Union Function

I'm trying to make my own union function and realizing how much I dislike LISP. The goal is to give the function two lists and it will return a set theoretic union of the two. My attempted solution has grown increasingly complex with the same result: NIL. I can't change that from being the result no matter what I do.
I was thinking of building a separate list in my "removeDuplicates" function below, but then idk how I'd return that with recursion. I think what's happening is my "removeDuplicates" function eventually returns an empty list (as intended) but then an empty list is return at every level of the stack when the recursion unfurls (starts returning values up the stack) but I could be wrong. I've always had trouble understanding recursion in detail. The code is below.
(defun rember (A LAT)
(cond
((null LAT) ())
((EQ (car LAT) A) (cdr LAT))
(T (cons (car LAT)(rember A (cdr LAT))))
)
)
(defun my_member (A LAT)
(cond
((null LAT) nil)
((EQ (car LAT) A) T)
(T (my_member A (cdr LAT)))
)
)
(defun removeDuplicates (L)
(cond
((null L) '())
((my_member (car L) (cdr L)) (rember (car L) L) (removeDuplicates (cdr L)))
(T (removeDuplicates (cdr L)))
)
)
(defun my_union (A B)
(setq together(append A B))
(removeDuplicates together)
)
I'm aware most people are not a fan of this format of LISP code, but I prefer it. It allows me to see how parentheses line up better than if you just put all the closing parentheses together at the end of functions and condition blocks.
If I run (my_union '(a b) '(b c)) for example, the result is NIL.
When you call removeDuplicates recursively in the last condition, you're not combining the result with the car of the list, so you're discarding that element.
You're also not using the result of rember.
(defun removeDuplicates (L)
(cond
((null L) '())
((my_member (car L) (cdr L))
(cons (car L)
(removeDuplicates
(rember (car L) (cdr L))
))
)
(T (cons (car L) (removeDuplicates (cdr L))))
)
)
Here's a simple, obvious, union function:
(defun union/tfb (&rest lists)
;; compute the union of any number of lists, implicitly using EQL
(labels ((union/spread (l1 ls)
;; UNION/SPREAD just exists to avoid the impedance
;; mismatch in argument convention
(if (null ls)
l1
(let ((result l1))
(destructuring-bind (l2 . more) ls
(dolist (e l2 (union/spread result more))
(pushnew e result)))))))
(union/spread (first lists) (rest lists))))
I think this is reasonably natural CL, although of course the whole point of using a language like CL is avoiding endless wheel-reinvention like this.
So the rules of the game perhaps say you're not allowed to use PUSHNEW: well, you can easily can replace it with a conditional involving MEMBER:
(defun union/tfb (&rest lists)
;; compute the union of any number of lists, implicitly using EQL
(labels ((union/spread (l1 ls)
;; UNION/SPREAD just exists to avoid the impedance
;; mismatch in argument convention
(if (null ls)
l1
(let ((result l1))
(destructuring-bind (l2 . more) ls
(dolist (e l2 (union/spread result more))
;; Really use PUSHNEW for this
(unless (member e result)
(setf result (cons e result)))))))))
(union/spread (first lists) (rest lists))))
And perhaps you are also not allowed to use MEMBER: well you can easily write a predicate which does what you need:
(defun union/tfb (&rest lists)
;; compute the union of any number of lists, implicitly using EQL
(labels ((union/spread (l1 ls)
;; UNION/SPREAD just exists to avoid the impedance
;; mismatch in argument convention
(if (null ls)
l1
(let ((result l1))
(destructuring-bind (l2 . more) ls
(dolist (e l2 (union/spread result more))
;; Really use MEMBER for this, and in fact
;; PUSHNEW
(unless (found-in-p e result)
(setf result (cons e result))))))))
(found-in-p (e list)
;; is e found in LIST? This exists only because we're not
;; meant to use MEMBER
(cond ((null list) nil)
((eql e (first list)) t)
(t (found-in-p e (rest list))))))
(union/spread (first lists) (rest lists))))
If you want the result to be a set with unique elements even if the first list is not you can trivially do that (note CL's UNION does not promise this, and you can get the same result with the earlier version of UNION/TFB by (union/tfb '() ...)):
(defun union/tfb (&rest lists)
;; compute the union of any number of lists, implicitly using EQL
(labels ((union/spread (l1 ls)
;; UNION/SPREAD just exists to avoid the impedance
;; mismatch in argument convention
(if (null ls)
l1
(let ((result l1))
(destructuring-bind (l2 . more) ls
(dolist (e l2 (union/spread result more))
;; Really use MEMBER for this, and in fact
;; PUSHNEW
(unless (found-in-p e result)
(setf result (cons e result))))))))
(found-in-p (e list)
;; is e found in LIST? This exists only because we're not
;; meant to use MEMBER
(cond ((null list) nil)
((eql e (first list)) t)
(t (found-in-p e (rest list))))))
(union/spread '() lists)))
Finally if the rules prevent you using iterative constructs and assignment you can do that too:
(defun union/tfb (&rest lists)
;; compute the union of any number of lists, implicitly using EQL
(labels ((union/spread (l1 ls)
;; UNION/SPREAD just exists to avoid the impedance
;; mismatch in argument convention
(if (null ls)
l1
(union/loop l1 (first ls) (rest ls))))
(union/loop (result l more)
;; UNION/LOOP is just an iteration
(if (null l)
(union/spread result more)
(destructuring-bind (e . remainder) l
(union/loop (if (found-in-p e result)
result
(cons e result))
remainder more))))
(found-in-p (e list)
;; is e found in LIST? This exists only because we're not
;; meant to use MEMBER
(cond ((null list) nil)
((eql e (first list)) t)
(t (found-in-p e (rest list))))))
(union/spread '() lists)))
The final result of all these changes is something which is, perhaps, very pure, but is not natural CL at all: something like it might be more natural in Scheme (albeit not gratuitously replacing MEMBER with a home-grown predicate like this).
One way to test your Common Lisp code is to ask your interpreter to TRACE functions:
(trace removeDuplicates my_member rember)
To avoid having too many traces, use small examples.
First, let's try with an empty list; this is an example from the REPL ("read eval print loop"), tested with SBCL, while in the "SO" package (StackOverflow); the trace is printed a bit indented, a is numbered according to the depth of the recursion. Here the call is not recursive and terminates right away:
SO> (removeduplicates nil)
0: (SO::REMOVEDUPLICATES NIL)
0: REMOVEDUPLICATES returned NIL
NIL
This works, let's try an example with a singleton list, where there is obviously no duplicate:
SO> (removeduplicates '(1))
0: (SO::REMOVEDUPLICATES (1))
1: (SO::MY_MEMBER 1 NIL)
1: MY_MEMBER returned NIL
1: (SO::REMOVEDUPLICATES NIL)
1: REMOVEDUPLICATES returned NIL
0: REMOVEDUPLICATES returned NIL
NIL
removeDuplicate calls my_member, which correctly returns nil, followed by a recursive call to removeDuplicates with nil, which correctly returns nil. There is however a problem because then, the outermost call returns nil too, which is incorrect.
Looking at the trace, we have to look back at the code to find a place where my_member is called, followed by a recursive call to removeDuplicates. There is only one place wher my_member is called, as a test to the second clause in the cond;
Since the result is nil for that test, the next clause is tried, in that case the default case:
(cond
...
;; this is the call to my_member (= nil)
((my_member (car L) (cdr L)) ...)
;; this is the recursive call
(t (removeDuplicates (cdr L))))
The value of the cond is the one given by the last (removeDuplicates (cdr L)), which just does not retain the existing elements in front of L. If you were mutating a sequence, you could just recurse down the subsequence and ignore the previous elements: in that case the caller would still hold a reference to the original sequence, which would get its element removed by a side-effect of your functions. But here you are following a strictly immutable approach, and you have to recontruct a list as a return value.
In other words, removeDuplicates is expressed as: return a new list which contains the same elements as the original list, but without duplicates.
So you have to add (car L) in front of (removeDuplicates (cdr L)).
(defun removeDuplicates (L)
(cond
((null L) '())
((my_member (car L) (cdr L)) (rember (car L) L) (removeDuplicates (cdr L)))
(T (cons (car L)
(removeDuplicates (rest L))))))
Let's test:
SO> (removeduplicates '())
0: (SO::REMOVEDUPLICATES NIL)
0: REMOVEDUPLICATES returned NIL
NIL
SO> (removeduplicates '(1))
0: (SO::REMOVEDUPLICATES (1))
1: (SO::MY_MEMBER 1 NIL)
1: MY_MEMBER returned NIL
1: (SO::REMOVEDUPLICATES NIL)
1: REMOVEDUPLICATES returned NIL
0: REMOVEDUPLICATES returned (1)
(1)
You can test with a longer list (without duplicates), the result is correct, but the trace is longer.
Now, let's add duplicates:
SO> (removeduplicates '(1 2 2 1))
0: (SO::REMOVEDUPLICATES (1 2 2 1))
1: (SO::MY_MEMBER 1 (2 2 1))
2: (SO::MY_MEMBER 1 (2 1))
3: (SO::MY_MEMBER 1 (1))
3: MY_MEMBER returned T
2: MY_MEMBER returned T
1: MY_MEMBER returned T
1: (SO::REMBER 1 (1 2 2 1))
1: REMBER returned (2 2 1)
1: (SO::REMOVEDUPLICATES (2 2 1))
2: (SO::MY_MEMBER 2 (2 1))
2: MY_MEMBER returned T
2: (SO::REMBER 2 (2 2 1))
2: REMBER returned (2 1)
2: (SO::REMOVEDUPLICATES (2 1))
3: (SO::MY_MEMBER 2 (1))
4: (SO::MY_MEMBER 2 NIL)
4: MY_MEMBER returned NIL
3: MY_MEMBER returned NIL
3: (SO::REMOVEDUPLICATES (1))
4: (SO::MY_MEMBER 1 NIL)
4: MY_MEMBER returned NIL
4: (SO::REMOVEDUPLICATES NIL)
4: REMOVEDUPLICATES returned NIL
3: REMOVEDUPLICATES returned (1)
2: REMOVEDUPLICATES returned (2 1)
1: REMOVEDUPLICATES returned (2 1)
0: REMOVEDUPLICATES returned (2 1)
(2 1)
The result is correct (order does not matter).
So far, our tests are good.
You might not have identified the other problem in that function, namely that all calls to rember are useless, and frankly this is not necessarily easy to spot with the trace. But looking at the code, it should be clear if you write code to have little side-effects that the following clause calls (rember ...) for nothing:
((my_member (car L) (cdr L)) (rember (car L) L) (removeDuplicates (cdr L)))
A cond clause has for syntax (TEST . BODY), where BODY is a sequence of expressions that evaluates like a PROGN: the value of a PROGN is the value of its last clause, all intermediate clauses are only used for their side-effects. For example:
(progn
(print "I am here")
(* 10 3))
Here above, the call to PRINT returns a value, but it is discarded: the value of the enclosing PROGN is 30.
In your code, rember does no side-effect, and its return value is discarded. Just remove it:
(defun removeDuplicates (L)
(cond
((null L) '())
((my_member (car L) (cdr L))
(removeDuplicates (cdr L)))
(T (cons (first L)
(removeDuplicates (rest L))))))
I would write the same code as follows, personally:
(defun remove-duplicate-elements (list)
(when list
(let ((head (first list))
(tail (remove-duplicate-elements (rest list))))
(if (member head tail) tail (cons head tail)))))
Here is a remove-dupes that removes duplicates from a list in O(n) time using a hash table. It supports a custom equality function (which must be eq, eql, equal or `equalp) and a custom test function, so that any aspect of an item can be treated as the key.
(defun remove-dupes (list &key (test #'eql) (key #'identity))
(let ((hash (make-hash-table :test test)))
(loop for item in list
for item-key = (funcall key item)
for seen = (gethash item-key hash)
unless seen collect item and
do (setf (gethash item-key hash) t))))
For instance, suppose we have the assoc list ((a . 1) (a . 2) (b . 3) (c . 4) (b . 4)). We'd like to remove duplicates by car:
[1]> (remove-dupes '((a . 1) (a . 2) (b . 3) (c . 4) (b . 4)) :key #'car)
((A . 1) (B . 3) (C . 4))
Only the leftmost A, B and C entries are reported; the duplicates are suppressed. Now let's do it by cdr:
[2]> (remove-dupes '((a . 1) (a . 2) (b . 3) (c . 4) (b . 4)) :key #'cdr)
((A . 1) (A . 2) (B . 3) (C . 4))
The (b . 4) got culled due to the duplicated 4 value.
But, why do all this, when Common Lisp provides a remove-duplicates function (not to mention union).
remove-duplicates is more general than what I have here: it handles sequences, rather than just lists, so it works on vectors and strings. It has more keyword parameters.

A varaible independent its local scope

I tried to solve the twoSum Problem with primitive tools of car and cdr
Given an array of integers, return indices of the two numbers such
that they add up to a specific target.
You may assume that each input would have exactly one solution, and
you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
The idea is to take a x from nums, then check if x's complement (target -x) is member of set nums-x
The key logic is
if ((memberp complement (remove-first x nums))
then (list x complement))
Begin with a helper function try nums
(defun two-sum (nums target)
(try nums))
The main function:
(defun try (nums)
(let ((x (car nums))
(complement (- target x)))
(cond
((null x) '())
((memberp complement (remove-first x nums))
(list x complement))
(t (try (cdr nums)))
)))
Then I realize that nums in ((memberp complement (remove-first x nums)) should be stay unchanged and independent from the local scope of let.
How could get such a nums?
memberp and `remove-first'
(defun remove-first (item sequence)
(filter (lambda (x) (not (= x item)))
sequence))
(defun filter (predicate sequence)
(cond ((null sequence) nil)
((funcall predicate (car sequence))
(cons (car sequence)
(filter predicate
(cdr sequence))))
(t (filter predicate
(cdr sequence)))))
(defun memberp(item x)
(cond ((null x) 'false)
((equal item (car x)) x)
(t (memq item (cdr x)))))
Here is a simple recursive function to compute the indexes:
(defun two-sum (list target &optional (pos 0))
(if (null (cdr list))
nil
(let ((p (my-position (- target (car list)) list)))
(if p
(list pos (+ pos p))
(two-sum (cdr list) target (1+ pos))))))
(defun my-position (element list &optional (pos 0))
(cond ((null list) nil)
((eql element (car list)) pos)
(t (my-position element (cdr list) (1+ pos)))))
The function is initially called with the list and the target. The parameter pos, which initially is not passed to the function, is assigned automatically to 0, and in the subsequent calls it will be incremented by one, so that it tracks the index of the current element of the list.
The first condition checks if the list has less than two elements: if it is empty (or its cdr is empty) the result is nil since no solution is possibile (note that in Common Lisp (cdr nil) is nil).
Otherwise we compute the position of the “complement” of the number in the rest of the list (note that position is a primitive function, so I called my-position its rewriting). If the element is present, we return both pos and (+ pos p) (since the position found is relative to the current position), otherwise (my-position returns nil when no element is found) we recur on the rest of the list.
Note that with this method there is no need to consider every time all the elements of the list.

Check if element is in a tree

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))).

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).