I have a question need your help.
Writing a recursion function named list-number to list every number in list. For example, (list-number '(2 a 4 b)) => (2 4).
Here is my try. But it doesn't work. Could you help me figure out?
(defun list-number (x)
(cond ((numberp x) x)
((atom x) nil)
(t (cons (list-number (car x)) (list-number (cdr x))))))
Thanks for your help.
You are doing this:
(list-number '(2 a)) ; ==
(list-number '(2 . (a . ()))) ; ==
(cons (list-number '2) (list-number '(a . ())) ; ==
(cons (list-number '2) ; 2 is a number
(cons (list-number 'a) ; a is an atom
(list-number '()))) ; () is an atom ==
(cons 2 (cons nil nil))
; ==> (2 nil)
Your problem is that you cons before you know if it should be a part of the result or not.
How you should do it is:
check if it's the empty list, then result is the empty list
check if the first element is a number. then you cons this number to the recursion of the rest of the list.
if neither two hit then the first element is not supposed to be a part of the result. Just recurse to the rest of the list since it might have numbers as well.
With this logic..
(list-number '(2 . (a . ()))) ; ==
(cons '2 (list-number '(a . ()))) ; ==
(cons '2 (list-number '())) ; ==
(cons '2 '()) ; ==> (2)
This logic does not handle trees.
You mean this?
(defvar *test '(2 a 4 b))
(defun list-number (nl)
(cond ((numberp (car nl))
(cons (car nl) (list-number (cdr nl))))
((eql nil nl)
nil)
(t
(list-number (cdr nl)))))
(list-number *test)
(2 4)
BTW, if you want to write a tail recursive function, I recommend store statue in arguments, like:
(defvar *test '(2 a 4 b))
(defun list-number (head nl)
(cond ((eql nil nl)
head)
((numberp (car nl))
(list-number (append head (list (car nl))) (cdr nl)))
(t
(list-number head (cdr nl)))))
(list-number '() *test)
(2 4)
Related
How do I recursively merge jumping pairs of elements of a list of lists? I need to have
'((a b c) (e d f) (g h i))
from
'((a b) c (e d) f (g h) i)
My attempt
(define (f lst)
(if (or (null? lst)
(null? (cdr lst)))
'()
(cons (append (car lst) (list (cadr lst)))
(list (append (caddr lst) (cdddr lst))))))
works if I define
(define listi '((a b) c (d e) f))
from which I obtain
((a b c) (d e f))
by doing simply
(f listi)
but it does not work for longer lists. I know I need recursion but I don't know where to insert f again in the last sentence of my code.
A simpler case that your algorithm fails: (f '((1 2) 3)) should result in '((1 2 3)), but yours results in an error.
We will define some terms first:
An "element" is a regular element, like 1 or 'a.
A "plain list" is simply a list of "element"s with no nested list.
E.g., '(1 2 3) is a plain list. '((1 2) 3) is not a plain list.
A "plain list" is either:
an empty list
a cons of an "element" and the next "plain list"
A "list of jumping pairs" is a list of even length where the odd index has a "plain list", and the even index has an element. E.g., '((1) 2 (a) 4) is a "list of jumping pairs". A "list of jumping pairs" is either:
an empty list
a cons of
a "plain list"
a cons of an "element" and the next "list of jumping pairs"
We are done with terminology. Before writing the function, let's start with some examples:
(f '()) equivalent to (f empty)
should output '()
equivalent to empty
(f '((1 2) 3)) equivalent to (f (cons (cons 1 (cons 2 empty))
(cons 3
empty)))
should output '((1 2 3))
equivalent to (cons (cons 1 (cons 2 (cons 3 empty)))
empty)
(f '((1 2) 3 (4) a)) equivalent to (f (cons (cons 1 (cons 2 empty))
(cons 3
(cons (cons 4 empty)
(cons 'a
empty)))))
should output '((1 2 3) (4 a))
equivalent to (cons (cons 1 (cons 2 (cons 3 empty)))
(cons (cons 4 (cons 'a empty))
empty))
So, f is a function that consumes a "list of jumping pairs" and returns a list of "plain list".
Now we will write the function f:
(define (f lst)
???)
Note that the type of lst is a "list of jumping pairs", so we will perform a case analysis on it straightforwardly:
(define (f lst)
(cond
[(empty? lst) ???] ;; the empty list case
[else ??? ;; the cons case has
(first lst) ;; the "plain list",
(first (rest lst)) ;; the "element", and
(rest (rest lst)) ;; the next "list of jumping pairs"
???])) ;; that are available for us to use
From the example:
(f '()) equivalent to (f empty)
should output '()
equivalent to empty
we know that the empty case should return an empty list, so let's fill in the hole accordingly:
(define (f lst)
(cond
[(empty? lst) empty] ;; the empty list case
[else ??? ;; the cons case has
(first lst) ;; the "plain list",
(first (rest lst)) ;; the "element", and
(rest (rest lst)) ;; the next "list of jumping pairs"
???])) ;; that are available for us to use
From the example:
(f '((1 2) 3)) equivalent to (f (cons (cons 1 (cons 2 empty))
(cons 3
empty)))
should output '((1 2 3))
equivalent to (cons (cons 1 (cons 2 (cons 3 empty)))
empty)
we know that we definitely want to put the "element" into the back of the "plain list" to obtain the resulting "plain list" that we want:
(define (f lst)
(cond
[(empty? lst) empty] ;; the empty list case
[else ;; the cons case has:
???
;; the resulting "plain list" that we want
(append (first lst) (cons (first (rest lst)) empty))
;; the next "list of jumping pairs"
(rest (rest lst))
;; that are available for us to use
???]))
There's still the next "list of jumping pairs" left that we need to deal with, but we have a way to deal with it already: f!
(define (f lst)
(cond
[(empty? lst) empty] ;; the empty list case
[else ;; the cons case has:
???
;; the resulting "plain list" that we want
(append (first lst) (cons (first (rest lst)) empty))
;; the list of "plain list"
(f (rest (rest lst)))
;; that are available for us to use
???]))
And then we can return the answer:
(define (f lst)
(cond
[(empty? lst) empty] ;; the empty list case
[else ;; the cons case returns
;; the resulting list of "plain list" that we want
(cons (append (first lst) (cons (first (rest lst)) empty))
(f (rest (rest lst))))]))
Pattern matching (using match below) is insanely useful for this kind of problem -
(define (f xs)
(match xs
;; '((a b) c . rest)
[(list (list a b) c rest ...)
(cons (list a b c)
(f rest))]
;; otherwise
[_
empty]))
define/match offers some syntax sugar for this common procedure style making things even nicer -
(define/match (f xs)
[((list (list a b) c rest ...))
(cons (list a b c)
(f rest))]
[(_)
empty])
And a tail-recursive revision -
(define (f xs)
(define/match (loop acc xs)
[(acc (list (list a b) c rest ...))
(loop (cons (list a b c) acc)
rest)]
[(acc _)
acc])
(reverse (loop empty xs)))
Output for each program is the same -
(f '((a b) c (e d) f (g h) i))
;; '((a b c) (e d f) (g h i))
(f '((a b) c))
;; '((a b c))
(f '((a b) c x y z))
;; '((a b c))
(f '(x y z))
;; '()
(f '())
;; '()
As an added bonus, this answer does not use the costly append operation
There is no recursive case in your code so it will just work statically for a 4 element list. You need to support the following:
(f '()) ; ==> ()
(f '((a b c) d (e f g) h)) ; ==> (cons (append '(a b c) (list 'd)) (f '((e f g) h)))
Now this requires exactly even number of elements and that every odd element is a proper list. There is nothing wrong with that, but onw might want to ensure this by type checking or by adding code for what should happen when it isn't.
(define (odds lst)
(if (null? lst)
lst
(cons (car lst)
(if (or (null? lst)
(not (pair? (cdr lst))))
'()
(odds (cddr lst)))))
)
This function returns the odd-numbered elements; my issue is, I want to take the list it returns and reverse it (using the built in reverse function). I've been trying to use lambda to store it but the results don't change, also tried using set-cons! also, to no avail. The concept of using let in a recursive function seems to escape me. If someone could point me in the right direction it would be very much appreciated!
Pass the function's result to reverse in the place where you want the reversed list:
> (odds '(a b c d e))
'(a c e)
> (reverse (odds '(a b c d e)))
'(e c a)
> (let ((o (reverse (odds '(a b c d e))))) (append o o))
'(e c a e c a)
> (define (reverse-odds ls) (reverse (odds ls)))
> (reverse-odds '(5 6 a 9 "hi"))
'("hi" a 5)
Here is a snippet storing both the return and the result using let*
(define (odds lst)
(if(null? lst)
lst
(cons (car lst)
(if (or (null? lst)
(not(pair? (cdr lst))))
'()
(odds (cddr lst))))))
(define data (odds `(1 2 3 4 5 6 7 8 9) ) )
(let ((rev_odds ( reverse data )))
;do stuff with results
(display rev_odds)
)
You can skip worrying about a return value if you just cons directly onto the recursive result
(define (odds lst)
(if (null? lst)
null
(if (odd? (car lst))
(cons (car lst)
(odds (cdr lst)))
(odds (cdr lst)))))
(odds '(0 1 2 3 4 5 6 7))
;; => '(1 3 5 7)
One way to represent a "return" value is by adding a parameter to our recursive function. Below we use acc in our auxiliary helper function, loop. Usage of parameters like this is one common way to move the recursive call into tail position
(define (odds lst)
(define (loop acc lst)
(if (null? lst)
(reverse acc)
(if (odd? (car lst))
(loop (cons (car lst) acc)
(cdr lst))
(loop acc
(cdr lst)))))
(loop null lst))
(odds '(0 1 2 3 4 5 6 7))
;; => '(1 3 5 7)
Another way is to represent our return value is by way of a lambda, cont below. We simply call cont with the value we wish to return. The recursive call looks a little more complicated in this case as we have to construct a lambda that represents the new return value. The added benefit here is odds constructs the result in order; reverse is no longer necessary
(define (odds lst (cont identity))
(if (null? lst)
(cont null)
(if (odd? (car lst))
(odds (cdr lst) (lambda (acc)
(cont (cons (car lst) acc))))
(odds (cdr lst) cont))))
(odds '(0 1 2 3 4 5 6 7))
;; => '(1 3 5 7)
I want to duplicate every found element in a list. I have the idea but i can't make it right. Sample input is >(pass '(1 2 3 4 4)) will have the output (1 1 2 2 3 3 4 4 4 4). Anyone out there help me. Here is my code ..
(define duplicate
(lambda (mylist n)
(cond ((null? mylist) "Not found")
((< n 2) (cons (car mylist)
(duplicate mylist (+ n 1))))
(else
(duplicate (cdr mylist) 0)))))
(define pass
(lambda (mylist)
(duplicate list 0)))
I will appreaciate all valuable comments.
Just a couple of fixes (see the comments) and we're good to go:
(define duplicate
(lambda (mylist n)
(cond ((null? mylist) '()) ; base case must return the empty list
((< n 2) (cons (car mylist)
(duplicate mylist (+ n 1))))
(else
(duplicate (cdr mylist) 0)))))
(define pass
(lambda (mylist)
(duplicate mylist 0))) ; pass myList, not list
Notice that the procedure can be simplified a bit:
(define (pass lst)
(if (null? lst)
'()
(cons (car lst)
(cons (car lst)
(pass (cdr lst))))))
Or even better, using higher-order procedures for a more idiomatic solution:
(define (pass lst)
(foldr (lambda (ele acc) (list* ele ele acc))
'()
lst))
Yet another alternative:
(define (pass lst)
(append-map (lambda (ele) (list ele ele))
lst))
Anyway, it works as expected:
(pass '(1 2 3 4 4))
=> (1 1 2 2 3 3 4 4 4 4)
I would do it so:
(define (dup l)
(define (iter l co)
(if (null? l)
(co '())
(iter (cdr l)
(lambda (x)
(co (cons (car l) (cons (car l) x)))))))
(iter l (lambda (x) x)))
(dup '(1 2 3))
It may be simpler to treat duplicate as zipping a list with itself. Then flattening the resulting list.
In Scheme or Racket:
(require srfi/1)
(define (duplicate-list-members lox)
(flatten (zip lox lox)))
Though it runs in O(n) time, profiling may indicate that passing through the list twice is a bottleneck and justify rewriting the function. Or it might not.
Try using map and list
(define (duplicate my-list)
(flatten
(map
(lambda (x)
(list x x))
my-list)))`
Gives requested format:
> (duplicate (list 1 2 3 4 4))
'(1 1 2 2 3 3 4 4 4 4)
Remove duplicates in a MULTI-LEVEL list (using Common Lisp) without changing list's inner structure. This problem seems to be a hard nut and a big headache for me.
Source list:
(1 2 (6 5) 2 3 (5 4)) ==> Result: (1 (6) 2 3 (5 4))
Here's my not-working decision:
LispWokrs:
(defun F (l &optional (lst (remove-duplicates (flatten l))))
(cond
((null l) nil)
((atom (car l))
(if (member (car l) lst)
(cons (car l) (F (cdr l) (remove (car l) lst)))
(F (cdr l) lst)))
(t (cons (F (car l) lst) (F (cdr l) lst)))))
I tried to use lst for keeping a clear set (1 2 6 5 3 4) and I've been trying to remove an element from this set each time I add a new element.
But what I get is almost the same source sequence (parallel recursion...):
(f '(1 2 (6 5) 2 3 (5 4))) ==> (1 2 (6 5) 3 (5 4))
(f '(А ((B C E) D (B E A)))) ==> (А ((B C E) D (B E A)))
Then I searched over the net, but there was no decision for this problem.
Try this:
(defun multi-level-list-remove-duplicates (tree)
(let ((seen NIL))
(labels ((rec (l)
(cond
((null l) NIL)
((consp (car l)) (cons (rec (car l))
(rec (cdr l))))
((member (car l) seen) (rec (cdr l)))
(T (push (car l) seen)
(cons (car l) (rec (cdr l)))))))
(rec tree))))
This maintains a list of already-seen values in seen and removes these if seen again. The recursive function rec closes over this value and thus all the sub-lists share one seen variable for each call to multi-level-list-remove-duplicates.
i've got a problem: I need to find if list equal to the second one, for example:
(set%eq? '(1 2 3) '(1 2 3)) ===> #t
(set%eq? '(1 2 3) '(2 3 4)) ===> #f
That examples are correct in my program, but this one is not:
(set%eq? (quote ((quote one) (quote two) (quote three))) (quote ((quote one) (quote two)
(quote three)))) ====> #f but i need #t
what's wrong?
this is my program:
(define (set-eq? xs ys)
(cond ((and (null? xs) (null? ys)) #t)
((null? ys) #f)
((eq? (car xs) (car ys)) (set-eq? (cdr xs) (cdr ys)))
((eq? (car xs) (car (reverse ys))) (set-eq? (cdr xs) (cdr (reverse ys))))
(else #f)))
There are a couple of mistakes in the posted code, and FYI, the procedure tests whether two lists are equal, it's not really testing for equality between two sets:
(define (set-eq? xs ys)
(cond ((and (null? xs) (null? ys)) #t)
((or (null? xs) (null? ys)) #f) ; missing case
((equal? (car xs) (car ys)) (set-eq? (cdr xs) (cdr ys))) ; use equal?
; deleted unnecessary case here. Anyway, why are you reversing the list?
(else #f)))
Now this will work:
(set-eq? '(1 2 3) '(1 2 3))
=> #t
(set-eq? '(1 2 3) '(2 3 4))
=> #f
(set-eq? (quote ((quote one) (quote two) (quote three)))
(quote ((quote one) (quote two) (quote three))))
=> #t
In fact, this will work, too:
(equal? '(1 2 3) '(1 2 3))
=> #t
(equal? '(1 2 3) '(2 3 4))
=> #f
(equal? (quote ((quote one) (quote two) (quote three)))
(quote ((quote one) (quote two) (quote three))))
=> #t
...But this won't work, the lists are clearly different:
(set-eq? '(1 2 3 4) '(4 1 2 3))
=> #f
If you intended to test for equality between two sets, you have to completely rethink the algorithm. Here's an idea: write asubset? procedure that tests if a list is a subset of another list (that is: if all the elements in one list are contained in the other list), and then test whether (and (subset? l1 l2) (subset? l2 l1)) is true, if that happens, then they're equal according to the set definition of equality.
Base on the comments from OP it's clear that these are set-eq?
(set-eq? '(a b c) '(c b a)) ; ==> #t
(set-eq? '(a b c) '(b c a)) ; ==> #t
(set-eq? '() '()) ; ==> #t
(set-eq? '(a b) '(a b c)) ; ==> #f
(set-eq? '(a b c) '(a c)) ; ==> #f
If the lists are without duplicates one could iterate the first list and try to find it in the second. If found we recurse with the two lists without the match.
#!r6rs
(import (rnrs)
(rnrs lists))
(define (set-eq? xs ys)
(if (null? xs)
(null? ys) ; #t if both sets are empty, otherwise #f
(let ((cur (car xs)))
(and (memq cur ys) ; first element is found
(set-eq? <??> (remq <??> <??>)))))) ; recurse without first in both lists
There are ways to get this faster. E.q. Hash the first list and iterate the second. If all matches and hashtable-size is the same as the number of iterations it's #t.