List without nil in result Lisp - 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).

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.

Flattening lists (while removing 'nil' and keeping atoms after " . ") in lisp

I want to create a function that would flatten a list and remove all potential nil inside.
Expected behavior, example 1:
(myfunc '(a (b (c) (d)) (e f) (g (h)) nil)) => (a b c d e f g h)
Expected behavior, example 2:
(myfunc '(a . d)) => (a d)
my function so far:
(defun myfunc (l)
(cond
((atom l) nil)
((and (atom (car l)) (not (equal (car l) nil))) (cons (car l) (myfunc (cdr l))))
(t (append (myfunc (car l)) (myfunc (cdr l))))))
My function works as expected for the first example, but not the second.
I get:
(myfunc '(a . d)) => (a)
Why doesn't it keep that d?
Is there a way to fix it?
Perhaps you should think about what the flatten function should do, in plain English:
Base case: If flattening nil, return an empty list.
Base case: If flattening single atoms, return a list containing just that.
Recursive case: If flattening pairs, return a list appending the flattening of its car with the flattening of its cdr.
Here's how I'd implement the description I just gave:
(defun flatten (x)
(cond ((null x) x)
((atom x) (list x))
(t (nconc (flatten (car x)) (flatten (cdr x))))))

how to solve badly formed lambda in lisp?

I am trying to check if a list has a mountain aspect or not in lisp.
e.g:1,5,9,6,4,3
l is my list and aux is 0-the ascending part of l or 1-the descending part of the list.
muntemain just call munte starting with aux=0,the ascending part
my error is :
Badly formed lambda: (AND (< (CAR L) (CAR (CDR L))) (EQ AUX 0))
and I can't see the problem.Can someone help please?
(defun munte (l aux)
(cond
((and (atom l) (null aux)) NIL)
((and (null l) (null aux)) NIL)
((and (atom l) (eq aux 1)) T)
((and (null l) (eq aux 1) T)
((and (< (car l) (car(cdr l))) (eq aux 0)) (munte(cdr l) 0))
((and (or (> (car l) (cadr l)) (= (car l) (cadr l))) (eq aux 0))(munte(cdr l) 1))
( and (> (car l) (cadr l)) (eq aux 1)) (munte(cdr l) 1))
(T NIL)
)
)
(defun muntemain (l)
(cond
((> (car l) (cadr l)) NIL)
((< (length l) 2) NIL)
(T (munte l 0))
)
)
Formatting
As noted by Barmar, you really need to use an editor to help you with the parenthesis. There are many tutorials for installing Emacs+Slime. Take some time to install proper tools.
Don't use EQ for numbers and characters
An implementation is permitted to make "copies" of characters and
numbers at any time. The effect is that Common Lisp makes no guarantee
that eq is true even when both its arguments are "the same thing" if
that thing is a character or number.
Factorize tests
((and (atom l) (null aux)) NIL)
((and (null l) (null aux)) NIL)
((and (atom l) (eq aux 1)) T)
((and (null l) (eq aux 1) T)
From the definition of atom, NIL is an atom, so you don't need (null L). The different cases for aux can be grouped too. The clause below is sufficient to account for all the above ones:
((atom L) (eql aux 1))
But I don't understand why aux is not a boolean in the first place if you always bind it to 0 or 1. Just use t and nil and return aux in the above clause.
Use meaningful functions
(< (car l) (car(cdr l)))
Of course, (car(cdr ..)) is known as (cadr ..), but also as second. The above test is equivalent to:
(< (first L) (second L))
And what if your list has no second element? You will compare a number against nil and signal an error (not what you want). You need more tests. In muntemain, you seem to have a special case for when length is below 2, but the test is done only if the previous returns nil, which won't happen if an error is signaled.
An iterative alternative
Here is a completely different way to attack the problem, just to give you ideas.
(lambda (list)
(loop
;; memories
for px = nil then x
for pdx = nil then dx
;; current element
for x in list
;; first and second "derivatives" (signs only)
for dx = 1 then (signum (- x px))
for ddx = 0 then (signum (- dx pdx))
;; checks
sum ddx into total
always (and (<= dx 0) (<= -1 total 0))
finally (return (= total -1))))

Lisp function explanation

I have this example in LISP that removes from every level of a list a given number:
(defun remove_aux (e l)
(cond
((equal e l) nil)
((atom l) (list l))
(t(list(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))))))
(defun remove_el (e l)
(car (remove_aux e l)))
So, if it run like this: (remove_el 2 '(1 2 3 ((2 3 2) 4))) => (1 3 ((3) 4))
What I don't exactly understand is how this line works: (t(list(apply 'append (mapcar #'(lambda (l) (sterge_aux e l)) l))))
If I have the line without list and append ((t(mapcar #'(lambda (l) (remove_aux e l)) l))) the result is ((1) NIL (3) ((NIL (3) NIL) (4)))) if it has append but not list ( (t(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))) ) then the result is (1 3 3 4) and I don't get why because I did (apply 'append '((1) NIL (3) ((NIL (3) NIL) (4))))) in the Common Lisp console and the result was ((1 3 (NIL (3) NIL) (4))) so I'm really confused. Can somebody explain to me how this all works step by step?
I've annotated the code below to, I hope, explain what's going on. You're probably getting confused because l is getting redefined within a lambda... so the t line (in your example) has 2 "l"s on it but the first one isn't the same as the second one.
(defun remove_aux (e l)
(cond
((equal e l) nil) ;if e equals l return nil
((atom l) (list l)) ;if l is an atom return a list with just l in it
(t ; otherwise...
(list ;create a list
(apply 'append ; whose contents are created by appending
; together the lists that come out of this mapcar
; (apply the append method)
(mapcar #'(lambda (l) ( ; iterate over each of the elements in list l
; the one after the lambda not the one
; being passed to the lambda.
; (this is a horrible name choice
; lambda(l-item) would be much better)
remove_aux e l
; recursively call this method
; with e (which was passed in at the start)
; and l which isn't the l passed in,
; but is an entry of it (see why naming's
; so important?)
; this returns a list
; which will get appended by the append
; with the results of all the other calls
; to remove_aux for each item in the outer l
)
) l)
)))))
(defun remove_el (e l)
(car (remove_aux e l)
)
)
;; append elements of each list in argument together
(append '(a) '(b) '(c d) '(e)) ; ==> (a b c d e)
;; append elements of each sublist in argument
(apply #'append '((a) (b) (c d) (e))) ; ==> (a b c d e)
;; apply function on each element of list into new list
(mapcar #'(lambda (x) (+ x 1)) '(1 3 5 6)) ; ==> (2 4 6 7)
So what does the default case do in your function.. Well it applies itself to each sublist of lst and wrap it in a list so if l is '(a y 2 z) and e is 2, well then the result from mapcar is '((a) (y) () (z)) which is then the argument to apply-append which connects the elements together into one list again. When connecting the lists the element that was to be removed is an empty list and it's effectively ignored in the concatenation process.
Since all the lists appended you create in the helper, you could replace the apply-append with (mapcan #'(lambda (l) (remove_aux e l)) l). A more obvious way to do this would be using reduce while a more efficient way might use loop.
A procedure that achieve what you want to achieve is essentially like below procedure:
(defun remove-all (e l)"Removes all occurrences of e from a list l."
(cond
((null l) '())
((equal e (car l)) (remove-all e (cdr l)))
((not (atom (car l)))
(cons (remove-all e (car l))
(remove-all e (cdr l))))
(t (cons (car l)
(remove-all e (cdr l))))))
;note: the e is not neccessarily an atom, the l is not necessarily a list of atoms.
The procedure in your question has unnecessarily cluttered pieces, like append, maps etc.
if you recomment below i will explain the algorithm.
have a nice hack.

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.