How I can replace an append with a cons in my lisp program that reverses a list and all it's substrings?
(defun revert (l)
(cond
((atom l) l)
(t (append (revert (cdr l))
(list (revert (car l)))))))
(write (revert '(2 3 5 6 7 8 9 (4 5 (6)))))
With append the result is:
(((6) 5 4) 9 8 7 6 5 3 2)
By replacing append with cons i get something like this:
((((((((NIL (((NIL (NIL 6)) 5) 4)) 9) 8) 7) 6) 5) 3) 2)
I tried to watch some youtube tutorials but I still don't know how to do it correctly
As you have seen, you cannot simply replace append with cons, because they are two very different operators: append concatenates two lists in a single list, while cons takes an element and a list and returns a new list with the element in first position, and the rest of the list the second parameter.
One very simple way of solving your problem is simply to define your version of append using cons. For instance:
(defun my-append (list1 list2)
(cond ((null list1) list2)
(t (cons (car list1) (my-append (cdr list1) list2))))))
and the substituting append with my-append in the revert function.
Another way, is to define a new function that takes two lists and reverses the first one to the beginning of the second one. For instance:
(defun revert (l)
(rev2 l nil))
(defun rev2 (l1 l2)
(cond ((null l1) l2)
((atom (car l1)) (rev2 (cdr l1) (cons (car l1) l2)))
(t (rev2 (cdr l1) (cons (revert (car l1)) l2)))))
Related
I am attempting to write a function that calls a list recursively and reverses its order. However I need to make the function operate every other recursive level and I am attempting to pass boolean arguments to use as a flag. I am very new to Lisp and keep getting an Undefined function B error.
(defun revList (L b)
(cond ((null L) nil)
((b T)
(append (revList (cdr L nil))
(list (car L))))
((b nil)
(append (revList (cdr L T))
(list (car L))))))
(print (revlist '(1 (2 3) (4 (5 6)) (7 (8 (9 10)))) t))
The first problem, and the reason for the reported error message Undefined function B is that some test forms in the cond form are attempting to call a function b which has not been defined. In a cond form the test forms are evaluated, and the result is used to determine which branch should be used. When (b T) or (b nil) are evaluated, it is expected that b is a function or macro. Instead you should use an expression which evaluates to either a true value or nil here.
There is another problem of misplaced parentheses around a couple of calls to cdr: (cdr L nil) and (cdr L T).
Once these problems are fixed, the code looks like this:
(defun revList (L b)
(cond ((null L) nil)
(b
(append (revList (cdr L) nil)
(list (car L))))
(t
(append (revList (cdr L) t)
(list (car L))))))
I'm going to rewrite the above function using some better names to make things a bit more clear. Note that the idiomatic way to introduce an else clause into a cond form is to use t as the test form in the final clause:
(defun rev-helper-1 (xs reverse-p)
(cond ((null xs) nil)
(reverse-p
(append (rev-helper-1 (cdr xs) nil)
(list (car xs))))
(t
(append (rev-helper-1 (cdr xs) t)
(list (car xs))))))
This code compiles and runs, but probably does not do what is expected. When reverse-p is true the code does exactly the same thing as when it is false, except that the sense of reverse-p is flipped. So the code always reverses its input:
CL-USER> (rev-helper-1 '(1 2 3 4) t)
(4 3 2 1)
CL-USER> (rev-helper-1 '(1 2 3 4) nil)
(4 3 2 1)
Further, this code does not descend into nested lists:
CL-USER> (rev-helper-1 '(1 2 3 4 (a b c d (5 6 7 8))) nil)
((A B C D (5 6 7 8)) 4 3 2 1)
It isn't entirely clear from the OP post whether the desired goal is to reverse list elements on alternate recursive calls, or to reverse list elements in alternate levels of nesting. I suspect that the second goal is the correct one.
Reversing on Alternate Recursive Calls
To reverse list elements on alternating recursive calls, the code needs to cons the first element of the list back onto the front of the "reversed" remainder of the list whenever it is in a non-reversing call. In this way, every other element will be moved to the back of the list, and those moved to the back will be in reverse order in the final list.
(defun rev-helper-2 (xs reverse-p)
(cond ((null xs) nil)
(reverse-p
(append (rev-helper-2 (cdr xs) nil)
(list (car xs))))
(t
(cons (car xs)
(rev-helper-2 (cdr xs) t)))))
CL-USER> (rev-helper-2 '(1 2 3 4) t)
(2 4 3 1)
Reversing in Alternate Levels of Nesting
To reverse in alternate levels of nesting, the code needs distinguish between atoms and lists in the input.
If the first element of a list is an atom, and if the current level is a reversing level, then the first element is wrapped in a list and appended to the result of reversing the rest of the level. Otherwise, if the first element is an atom, and the current level is not a reversing level, then the first element is consed onto the front of "reversing" the rest of the level. In this second case "reversing" the rest of the level will not change the ordering of elements at this level, because reverse-p will be false for non-reversing levels; but the code still needs to walk over the list to see if any elements at this level are lists which require further processing.
Otherwise, the first element is a list. If the current level is a reversing level, then the first element must be "reversed", i.e., processed by the reversing function, then wrapped in a list and appended to the end of reversing the rest of the list. Otherwise the current level is not a reversing level, so the first element must be processed by the reversing function and consed onto the front of "reversing" the rest of the list.
(defun rev-helper-3 (xs reverse-p)
(cond ((null xs) nil)
((atom (car xs))
(if reverse-p
(append (rev-helper-3 (cdr xs) t)
(list (car xs)))
(cons (car xs)
(rev-helper-3 (cdr xs) nil))))
(reverse-p
(append (rev-helper-3 (cdr xs) t)
(list (rev-helper-3 (car xs) nil))))
(t
(cons (rev-helper-3 (car xs) t)
(rev-helper-3 (cdr xs) nil)))))
Using a let form to bind the results of (car xs) and (cdr xs) to a couple of descriptive identifiers reduces the number of calls to car and cdr and makes this a bit easier to read:
(defun rev-helper-4 (xs reverse-p)
(if (null xs) nil
(let ((first (car xs))
(rest (cdr xs)))
(cond ((atom first)
(if reverse-p
(append (rev-helper-4 rest t)
(list first))
(cons first
(rev-helper-4 rest nil))))
(reverse-p
(append (rev-helper-4 rest t)
(list (rev-helper-4 first nil))))
(t
(cons (rev-helper-4 first t)
(rev-helper-4 rest nil)))))))
Let's write a convenience function to make it nicer to call rev-helper-4:
(defun rev-alt (xss)
(rev-helper-4 xss t))
CL-USER> (rev-alt '(1 2 3 4))
(4 3 2 1)
CL-USER> (rev-alt '(1 2 3 4 (a b c d)))
((A B C D) 4 3 2 1)
CL-USER> (rev-alt '(1 2 3 4 (a b c d (5 6 7 8))))
((A B C D (8 7 6 5)) 4 3 2 1)
CL-USER> (rev-alt '(1 (2 3) (4 (5 6)) (7 (8 (9 10)))))
((7 ((9 10) 8)) (4 (6 5)) (2 3) 1)
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)))))
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.
I have no problem combining the lists but sorting them in ascending order is where i am struggling.
(define (combineASC l1 l2)
(cond
((null? l1) l2)
(#t (cons (car l1) (combineASC (cdr l1) l2)))
(sort l2 #'<))) ; I found this part in an online source
This is the output i get:
(combineASC '(2 4 6) '(1 4 5))
(2 4 6 1 4 5)
Does anyone have any suggestions for me?
So you're combining two input lists, each already sorted in ascending order. You want to "weave" them into one, also in ascending order.
For that, you just take both head elements (each from each input list) and compare; then you take the smallest out from its list, and combine further what you're left with - using same function.
There will be no sorting involved. The resulting list will be already sorted, by virtues of the process that defines it.
This operation is commonly called "merge". It preserves duplicates. Its duplicates-removing counterpart, merging two ordered lists into one as well, is known a "union". That is because these ordered (non-descending, or strictly ascending) lists can be seen as representation of sets.
Another subtlety to take note of is, what to do when the two head elements are equal. We've already decided to preserve the duplicates, yes, but which of the two to take out first?
Normally, it's the left one. Then when such defined merge operation is used as part of merge sort, the sort will be stable (of course the partitioning has to be defined properly for that too). Stable means, the original order of elements is preserved.
For example, if the sort is stable, when sorting by the first element of pairs, (3,1) (1,2) (3,3) is guaranteed to be sorted as (1,2) (3,1) (3,3) and not as (1,2) (3,3) (3,1).
So, following the skeleton of your code, we get
;; combine two non-decreasing lists into one non-decreasing list,
;; preserving the duplicates
(define (combineNONDECR l1 l2)
(cond
((null? l1) l2)
((null? l2) l1)
((<= (car l1) (car l2))
(cons (car l1) (combineNONDECR (cdr l1) l2)))
(t
(cons (car l2) (combineNONDECR l1 (cdr l2))))))
But if you really need the result to be in ascending order, as opposed to non-decreasing, then you'd have to tweak this a little bit - make the = case separate, and handle it separately, to stop the duplicates from creeping in (there are no duplicates in each of the ascending-order lists, but the lists might contain some duplicates between the two of them).
Because tail recursive :)
(define (merge-sorted . lists)
(define (%merge-sorted head tails)
(cond
((null? tails) head)
((null? (car tails))
(%merge-sorted head (cdr tails)))
(else (let ((sorted
(sort tails
(lambda (a b)
(<= (car a) (car b))))))
(%merge-sorted (cons (caar sorted) head)
(cons (cdar sorted) (cdr sorted)))))))
(reverse (%merge-sorted '() lists)))
(merge-sorted '(1 2 3) '(4 5 6 7 8 9) '(2 4 6) '(1 3 5 7))
it scales better :P
I think this is what Will was talking about:
(define (merge-sorted . lists)
(define (%swap-if-greater lists)
(define (%do-swap head next built tails)
(cond
((null? tails)
(append (reverse built)
(cond
((null? next) (list head))
((> (car head) (car next))
(list next head))
(else (list head next)))))
((> (car head) (car next))
(%do-swap head (car tails)
(cons next built) (cdr tails)))
(else (append (reverse built)
(list head) (list next) tails))))
(%do-swap (car lists)
(if (null? (cdr lists)) '() (cadr lists))
'() (if (null? (cdr lists)) '() (cddr lists))))
(define (%merge-sorted head tails)
(cond
((null? tails) head)
((null? (car tails))
(%merge-sorted head (cdr tails)))
(else (let ((sorted (%swap-if-greater tails)))
(%merge-sorted (cons (caar sorted) head)
(cons (cdar sorted)
(cdr sorted)))))))
(reverse
(%merge-sorted
'() (sort lists (lambda (a b) (<= (car a) (car b)))))))
Especially given Schemes... interesting position on booleans, I wouldn't be very enthusiastic about this one.
(defun merge (l1 l2)
(if (not (and (eql nil l1) (eql l2 nil))
(if (> (car l1) (car l2))
(cons (car l1) (merge (cdr l1) l2))
(cons (car l2) (merge (cdr l2) l1)))
;;;append the not-nil string to the rest.
)
that should work (you still need to complete the code, but the idea is clear)
note this code is in common-lisp.
look up merge sort for more info about the technique
How can I remove nested parentheses recursively in Common LISP Such as
(unnest '(a b c (d e) ((f) g))) => (a b c d e f g)
(unnest '(a b)) => (a b)
(unnest '(() ((((a)))) ())) => (a)
Thanks
Here's what I'd do:
(ql:quickload "alexandria")
(alexandria:flatten list)
That works mainly because I have Quicklisp installed already.
(defun flatten (l)
(cond ((null l) nil)
((atom l) (list l))
(t (loop for a in l appending (flatten a)))))
I realize this is an old thread, but it is one of the first that comes up when I google lisp flatten. The solution I discovered is similar to those discussed above, but the formatting is slightly different. I will explain it as if you are new to lisp, as I was when I first googled this question, so it's likely that others will be too.
(defun flatten (L)
"Converts a list to single level."
(if (null L)
nil
(if (atom (first L))
(cons (first L) (flatten (rest L)))
(append (flatten (first L)) (flatten (rest L))))))
For those new to lisp, this is a brief summary.
The following line declares a function called flatten with argument L.
(defun flatten (L)
The line below checks for an empty list.
(if (null L)
The next line returns nil because cons ATOM nil declares a list with one entry (ATOM). This is the base case of the recursion and lets the function know when to stop. The line after this checks to see if the first item in the list is an atom instead of another list.
(if (atom (first L))
Then, if it is, it uses recursion to create a flattened list of this atom combined with the rest of the flattened list that the function will generate. cons combines an atom with another list.
(cons (first L) (flatten (rest L)))
If it's not an atom, then we have to flatten on it, because it is another list that may have further lists inside of it.
(append (flatten (first L)) (flatten (rest L))))))
The append function will append the first list to the start of the second list.
Also note that every time you use a function in lisp, you have to surround it with parenthesis. This confused me at first.
You could define it like this for example:
(defun unnest (x)
(labels ((rec (x acc)
(cond ((null x) acc)
((atom x) (cons x acc))
(t (rec (car x) (rec (cdr x) acc))))))
(rec x nil)))
(defun flatten (l)
(cond ((null l) nil)
((atom (car l)) (cons (car l) (flatten (cdr l))))
(t (append (flatten (car l)) (flatten (cdr l))))))
Lisp has the function remove to remove things. Here I use a version REMOVE-IF that removes every item for which a predicate is true. I test if the thing is a parenthesis and remove it if true.
If you want to remove parentheses, see this function:
(defun unnest (thing)
(read-from-string
(concatenate
'string
"("
(remove-if (lambda (c)
(member c '(#\( #\))))
(princ-to-string thing))
")")))
Note, though, as Svante mentions, one does not usually 'remove' parentheses.
Most of the answers have already mentioned a recursive solution to the Flatten problem. Using Common Lisp Object System's multiple dispatching you could solve the problem recursively by defining 3 methods for 3 possible scenarios:
(defmethod flatten ((tree null))
"Tree is empty list."
())
(defmethod flatten ((tree list))
"Tree is a list."
(append (flatten (car tree))
(flatten (cdr tree))))
(defmethod flatten (tree)
"Tree is something else (atom?)."
(list tree))
(flatten '(2 ((8) 2 (9 (d (s (((((a))))))))))) ; => (2 8 2 9 D S A)
Just leaving this here as I visited this question with the need of only flattening one level and later figure out for myself that (apply 'concatenate 'list ((1 2) (3 4) (5 6 7))) is a cleaner solution in that case.
This is a accumulator based approach. The local function %flatten keeps an accumulator of the tail (the right part of the list that's already been flattened). When the part remaining to be flattened (the left part of the list) is empty, it returns the tail. When the part to be flattened is a non-list, it returns that part prefixed onto the tail. When the part to be flattened is a list, it flattens the rest of the list (with the current tail), then uses that result as the tail for flattening the first part of the list.
(defun flatten (list)
(labels ((%flatten (list tail)
(cond
((null list) tail)
((atom list) (list* list tail))
(t (%flatten (first list)
(%flatten (rest list)
tail))))))
(%flatten list '())))
CL-USER> (flatten '((1 2) (3 4) ((5) 6) 7))
(1 2 3 4 5 6 7)
I know this question is really old but I noticed that nobody used the push/nreverse idiom, so I am uploading that here.
the function reverse-atomize takes out each "atom" and puts it into the output of the next call. At the end it produces a flattened list that is backwards, which is resolved with the nreverse function in the atomize function.
(defun reverse-atomize (tree output)
"Auxillary function for atomize"
(if (null tree)
output
(if (atom (car tree))
(reverse-atomize (cdr tree) (push (car tree) output))
(reverse-atomize (cdr tree) (nconc (reverse-atomize (car tree)
nil)
output)))))
(defun atomize (tree)
"Flattens a list into only the atoms in it"
(nreverse (reverse-atomize tree nil)))
So calling atomize '((a b) (c) d) looks like this:
(A B C D)
And if you were to call reverse-atomize with reverse-atomize '((a b) (c) d) this would occur:
(D C B A)
People like using functions like push, nreverse, and nconc because they use less RAM than their respective cons, reverse, and append functions. That being said the double recursive nature of reverse-atomize does come with it's own RAMifications.
This popular question only has recursive solutions (not counting Rainer's answer).
Let's have a loop version:
(defun flatten (tree &aux todo flat)
(check-type tree list)
(loop
(shiftf todo tree nil)
(unless todo (return flat))
(dolist (elt todo)
(if (listp elt)
(dolist (e elt)
(push e tree))
(push elt flat))))))
(defun unnest (somewhat)
(cond
((null somewhat) nil)
((atom somewhat) (list somewhat))
(t
(append (unnest (car somewhat)) (unnest (cdr somewhat))))))
I couldn't resist adding my two cents. While the CL spec does not require tail call optimization (TCO), many (most?) implementations have that feature.
So here's a tail recursive version that collects the leaf nodes of a tree into a flat list (which is one version of "removing parentheses"):
(defun flatten (tree &key (include-nil t))
(check-type tree list)
(labels ((%flatten (lst accum)
(if (null lst)
(nreverse accum)
(let ((elem (first lst)))
(if (atom elem)
(%flatten (cdr lst) (if (or elem include-nil)
(cons elem accum)
accum))
(%flatten (append elem (cdr lst)) accum))))))
(%flatten tree nil)))
It preserves null leaf nodes by default, with the option to remove them. It also preserves the left-to-right order of the tree's leaf nodes.
Note from Google lisp style guide about TCO:
You should favor iteration over recursion.
...most serious implementations (including SBCL and CCL) do implement proper tail calls, but with restrictions:
The (DECLARE (OPTIMIZE ...)) settings must favor SPEED enough and not favor DEBUG too much, for some compiler-dependent meanings of "enough" and "too much".
And this from SBCL docs:
... disabling tail-recursion optimization ... happens when the debug optimization quality is greater than 2.