Deep-reverse for trees in Scheme (Lisp) - data-structures

I have a deep reverse for a basic tree data structure in Scheme
(define (deep-reverse t)
(cond ((null? t) '())
((not (pair? t)) t)
(else (cons (deep-reverse (cdr t)) (deep-reverse (car t))))))
(define stree (cons (list 1 2) (list 3 4)))
1 ]=> (deep-reverse stree)
;Value: (((() . 4) . 3) (() . 2) . 1)
I feel like a cleaner, better result would be:
(4 3 (2 1))
Can anyone provide some guidance as to where I'm going wrong in my deep-reverse function? Thank you.

It's better to split the task into simple operations instead of trying to do all at once. What you want to achieve can be described like this: Reverse the current list itself, then deep-reverse all sublists in it (or the other way round, the order of the two steps doesn't really matter. I choose this order because it results in nicer formatting of the source code).
Now, there already is a function in the standard library for simply reversing a list, reverse. So all you need to do is to combine that with the recursion on those elements that are sublists:
(define (deep-reverse t)
(map (lambda (x)
(if (list? x)
(deep-reverse x)
x))
(reverse t)))

Try this:
(define (deep-reverse t)
(let loop ((t t)
(acc '()))
(cond ((null? t) acc)
((not (pair? t)) t)
(else (loop (cdr t)
(cons (loop (car t) '()) acc))))))
Call it like this:
(define stree (cons (list 1 2) (list 3 4)))
(deep-reverse stree)
> (4 3 (2 1))
For creating a reversed list, one technique is to accumulate the answer in a parameter (I usually call it acc). Since we're operating on a list of lists, the recursion has to be called on both the car and the cdr part of the list. Lastly, I'm using a named let as a shorthand for avoiding the creation of an extra function, but the same result could be obtained by defining a helper function with two parameters, the tree and the accumulator:
(define (deep-reverse t)
(aux t '()))
(define (aux t acc)
(cond ((null? t) acc)
((not (pair? t)) t)
(else (aux (cdr t)
(cons (aux (car t) '()) acc)))))

I think it better to reverse a list based on its element count:
an empty list is reverse, a single element list is also reverted, more than 1 element is concatenation of the reverse of tail and head.
(defun deep-reverse (tree)
(cond ((zerop (length tree)) nil)
((and (= 1 (length tree)) (atom (car tree))) tree)
((consp (car tree)) (append (deep-reverse (cdr tree))
(list (deep-reverse (car tree)))))
(t (append (deep-reverse (cdr tree)) (list (car tree))))))

The following worked for me:
(define (deep-reverse tree)
(define (deep-reverse-iter items acc)
(cond
((null? items) acc)
((not (pair? items)) items)
(else (deep-reverse-iter
(cdr items)
(cons (deep-reverse (car items)) acc)))))
(deep-reverse-iter tree ()))
(define x (list (list 1 2) (list 3 4 (list 5 6))))
(newline)
(display (deep-reverse x))
It prints (((6 5) 4 3) (2 1)) as expected and uses the minimum of standard library functions: pair? to check if the tree is a cons and null? to check for an empty tree/list.
This solution for trees is a generalization of the reverse function for lists:
(define (reverse items)
(define (reverse-iter items acc)
(cond
((null? items) acc)
((not (pair? items)) items)
(else (reverse-iter (cdr items) (cons (car items) acc)))))
(reverse-iter items ()))
the difference being that deep-reverse is also applied to car items

Related

Scheme: Split list into list of two sublists of even and odd positions

I'm trying to use direct recursion to sort a list into a list of sublists of even and odd positions.
So (split '(1 2 3 4 5 6)) returns ((1 3 5) (2 4 6))
and (split '(a 2 b 3)) returns ((a b) (2 3))
So far, I have the following code:
(define split
(lambda (ls)
(if (or (null? ls) (null? (cdr ls)))
(values ls '())
(call-with-values
(lambda () (split (cddr ls)))
(lambda (odds evens)
(values (cons (car ls) odds)
(cons (cadr ls) evens)))))))
However, now I'm stumped on how to store multiple outputs into a single list.
I know that calling it like this:
(call-with-values (lambda () (split '(a b c d e f))) list)
returns a list of sublists, however I would like the function itself to return a list of sublists. Is there a better way to do this that doesn't involve the use of values and call-with-values?
Sure. Here's an adapted version of your code:
(define (split ls)
(if (or (null? ls) (null? (cdr ls)))
(list ls '())
(let ((next (split (cddr ls))))
(list (cons (car ls) (car next))
(cons (cadr ls) (cadr next))))))
One thing that I like about the code in the question is that it uses odds and evens in a way that reflects the specification.
The objectives of this solution are:
Readability.
To reflect the language of the specification in the code.
To use O(n) space during execution.
It uses an internal function with accumulators and a trampoline.
#lang racket
;; List(Any) -> List(List(Any) List(Any))
(define (split list-of-x)
(define end-of-list (length list-of-x))
;; List(Any) List(Any) List(Any) Integer -> List(List(Any) List(Any))
(define (looper working-list odds evens index)
(cond [(> index end-of-list)
(list (reverse odds)
(reverse evens))]
[(odd? index)
(looper (rest working-list)
(cons (car working-list) odds)
evens
(add1 index))]
[(even? index)
(looper (rest working-list)
odds
(cons (car working-list) evens)
(add1 index))]
[else
(error "split: unhandled index condition")]))
(looper list-of-x null null 1))
Here's an answer that should be clear if you are familiar with match syntax. It is identical in form and function to Chris Jester-Young's answer, but uses match to clarify list manipulation.
#lang racket
(define (split ls)
(match ls
[`(,first ,second ,rest ...)
(match (split rest)
[`(,evens ,odds) (list (cons first evens)
(cons second odds))])]
[_ (list ls '())]))
(: split ((list-of natural) -> (list-of (list-of natural))))
(define split
(lambda (xs)
(list (filter even? xs) (filter odd? xs))))
(: filter ((%a -> boolean) (list-of %a) -> (list-of %a)))
(define filter
(lambda (p xs)
(fold empty (lambda (first result)
(if (p first)
(make-pair first result)
result)) xs)))
(check-expect (split (list 1 2 3 4 5 6)) (list (list 2 4 6) (list 1 3 5)))
i think this one is also really easy to understand..

Same-parity in Scheme

I am trying to solve the exercise 2.20 from SICP book. The exercise -
Write a procedure same-parity that takes one or more integers and returns a list of
all the arguments that have the same even-odd parity as the first argument. For example,
(same-parity 1 2 3 4 5 6 7)
(1 3 5 7)
(same-parity 2 3 4 5 6 7)
(2 4 6)
My code -
(define same-parity (lambda (int . l)
(define iter-even (lambda (l2 rl)
(cons ((null? l2) rl)
((even? (car l2))
(iter-even (cdr l2) (append rl (car l2))))
(else (iter-even (cdr l2) rl)))))
(define iter-odd (lambda (l2 rl)
(cons ((null? l2) rl)
((odd? (car l2))
(iter-odd (cdr l2) (append rl (car l2))))
(else (iter-odd (cdr l2) rl)))))
(if (even? int) (iter-even l (list int))
(iter-odd l (list int)))))
For some reason I am getting an error saying "The object (), passed as the first argument to cdr, is not the correct type". I tried to solve this for more than two hours, but I cant find any reason why it fails like that. Thanks for hlep.
Try this:
(define same-parity
(lambda (int . l)
(define iter-even
(lambda (l2 rl)
(cond ((null? l2) rl)
((even? (car l2))
(iter-even (cdr l2) (append rl (list (car l2)))))
(else (iter-even (cdr l2) rl)))))
(define iter-odd
(lambda (l2 rl)
(cond ((null? l2) rl)
((odd? (car l2))
(iter-odd (cdr l2) (append rl (list (car l2)))))
(else (iter-odd (cdr l2) rl)))))
(if (even? int)
(iter-even l (list int))
(iter-odd l (list int)))))
Explanation:
You are using cons instead of cond for the different conditions
in the part where append is called, the second argument must be a proper list (meaning: null-terminated) - but it is a cons-pair in your code. This was causing the error, the solution is to simply put the second element inside a list before appending it.
I must say, using append to build an output list is frowned upon. You should try to write the recursion in such a way that cons is used for creating the new list, this is more efficient, too.
Some final words - as you're about to discover in the next section of SICP, this problem is a perfect fit for using filter - a more idiomatic solution would be:
(define (same-parity head . tail)
(if (even? head)
(filter even? (cons head tail))
(filter odd? (cons head tail))))
First, I check the first element in the list. If it is even, I call the procedure that forms a list out of only the even elements. Else, I call the procedure that forms a list out of odd elements.
Here's my code
(define (parity-helper-even B)(cond
((= 1 (length B)) (cond
((even? (car B)) B)
(else '())
))
(else (cond
((even? (car B)) (append (list (car B)) (parity-helper-even (cdr B))))
(else (parity-helper-even(cdr B)))
))))
(define (parity-helper-odd B)(cond
((= 1 (length B)) (cond
((odd? (car B)) B)
(else '())
))
(else (cond
((odd? (car B)) (append (list (car B)) (parity-helper-odd (cdr B))))
(else (parity-helper-odd (cdr B)))
))))
(define (same-parity first . L) (cond
((even? first) (parity-helper-even (append (list first) L)))
(else (parity-helper-odd (append (list first) L)))))
(same-parity 1 2 3 4 5 6 7)
;Output (1 3 5 7)
While you are traversing the list, you might as well just split it into even and odd parities. As the last step, choose the one you want.
(define (parities args)
(let looking ((args args) (even '()) (odd '()))
(if (null? args)
(values even odd)
(let ((head (car args)))
(if (even? head)
(looking (cdr args) (cons head even) odd)
(looking (cdr args) even (cons head odd)))))))
(define (same-parity head . rest)
(let-values ((even odd) (parities (cons head rest)))
(if (even? head)
even
odd)))
Except for homework assignments, if you are going to look for one then you are likely to need the other. Said another way, you'd find yourself using parities more frequently in practice.
You could simply filter elements by parity of first element:
(define (same-parity x . y)
(define (iter z filter-by)
(cond ((null? z) z)
((filter-by (car z))
(cons (car z) (iter (cdr z) filter-by)))
(else (iter (cdr z) filter-by))))
(iter (cons x y) (if (even? x) even? odd?)))
And try:
(same-parity 1 2 3 4 5 6 7)
(same-parity 2 3 4 5 6 7)

How to determine if a list has an even or odd number of atoms

tScheme novice question:
I need to determine if a list contains an even or odd amount of atoms using recursion. I know the easy way is to get list length and determine if it is even or odd, but I would like to see hows it's done using recursion.
(oddatom
(LIST 'x 'y 'v 'd 'r 'h 'y))
should return #t, while
(oddatom
'((n m) (f p) l (u k p)))
should return #f
appreciate the help.
Here's my version of the solution:
(define (oddatom? lst)
(let recur ((odd #f)
(x lst))
(cond ((null? x) odd)
((pair? x) (recur (recur odd (car x)) (cdr x)))
(else (not odd)))))
I like Chris Jester-Young's answer, but I think it's worth providing a tail-recursive version that maintains its own stack as well. Note that this is an exercise in converting non-tail recursion into tail recursion, which is an imporant technique for some algorithms in Scheme. In this case, though, it's probably not all that important, and the code in Chris Jester-Young's answer does feel much more natural. So take this as an exercise, not necessarily a significant improvement.
The idea here is that the inner function, odd?, takes a list of things, and a value indicating whether an odd number of atoms (other than the empty list) have been seen so far.
(define (oddatom? thing)
(let odd? ((things (list thing))
(result #f))
(cond
;; We're out of things to see. Did we see an odd number of things?
((null? things)
result)
;; Our list of things has the form ((x . y) …), so we recurse on
;; (x y …), with the *same* value for result, since we haven't
;; "seen" x or y yet, we've just "unwrapped" them.
((pair? (car things))
(odd? (cons (caar things) (cons (cdar things) (cdr things))) result))
;; Our list of things has the form (() …), so we recurse on
;; (…), with the *same* value for result, since we haven't "seen" any
;; additional atoms.
((null? (car things))
(odd? (cdr things) result))
;; Our list of things has the form (<atom> …), so we recurse on (…),
;; but with a flipped value for result, since we've seen one more atom.
(else
(odd? (cdr things) (not result))))))
The last two cases could be combined, making the second recursive argument based on the value of (null? (car things)) as:
(define (oddatom? thing)
(let odd? ((things (list thing))
(result #f))
(cond
((null? things)
result)
((pair? (car things))
(odd? (cons (caar things) (cons (cdar things) (cdr things))) result))
(else
(odd? (cdr things) (if (null? (car things))
result
(not result)))))))
I'd go for this:
(define (oddatom lst)
(cond
((null? lst) #f)
((not (pair? lst)) #t)
(else (not (eq? (oddatom (car lst)) (oddatom (cdr lst)))))))
which means:
the empty list is not odd (#f)
an atom is odd (#t)
otherwise, one and only one of the car or the cdr of the list may be odd (exclusive or).
Test cases (in Racket), including improper lists:
(require rackunit)
(check-equal? (oddatom (list 'x 'y 'v 'd 'r 'h 'y)) #t)
(check-equal? (oddatom '((n m) (f p) l (u k p))) #f)
(check-equal? (oddatom '(a (b) c)) #t)
(check-equal? (oddatom (cons 1 2)) #f)
(check-equal? (oddatom 1) #t)
(check-equal? (oddatom '(1 (2 . 3))) #t)
Here is one:
(define (odd-atom? obj)
(and (not (null? obj))
(or (not (pair? obj))
(let ((this? (odd-atom? (car obj)))
(rest? (odd-atom? (cdr obj))))
(or (and (not this?) rest?)
(and (not rest?) this?))))))
or, learning from #uselpa to simplify the 'or this? rest?' logic above, another one:
(define (odd-atom? obj)
(and (not (null? obj))
(or (not (pair? obj))
(not (eq? (odd-atom? (car obj))
(odd-atom? (cdr obj)))))))
If '() is an atom (like it is in CommonLisp where '() is also T), it should be (odd-atom? '(() () ())) is #t:
(define (odd-atom? obj)
(and (not (null? obj))
(or (not (pair? obj))
(let ((this? (or (null? (car obj))
(odd-atom? (car obj))))
(rest? (odd-atom? (cdr obj))))
(not (eq? this? rest?))))))
> (odd-atom? '())
#f
> (odd-atom? '(()))
#t
> (odd-atom? '(() () ()))
#t
> (odd-atom? '(() ()))
#f
> (odd-atom? '(() (a)))
#f
> (odd-atom? '(() (a b)))
#t
> (odd-atom? '((a) (a b)))
#t
> (odd-atom? '((a b) (a b)))
#f
>

How to sort disorder list of numbers in scheme

What it the proper way to sort a list with values in Scheme? For example I have the values which are not ordered:
x1, x5, x32 .... xn
or
3, 4, 1, 3, 4, .. 9
First I want to for them by increase number and display them in this order:
x1, xn, x2, xn-1
or
1, 6, 2, 5, 3, 4
Any help will be valuable.
This is the same question you posted before, but with a small twist. As I told you in the comments of my answer, you just have to sort the list before rearranging it. Here's a Racket solution:
(define (interleave l1 l2)
(cond ((empty? l1) l2)
((empty? l2) l1)
(else (cons (first l1)
(interleave l2 (rest l1))))))
(define (zippy lst)
(let-values (((head tail) (split-at
(sort lst <) ; this is the new part
(quotient (length lst) 2))))
(interleave head (reverse tail))))
It works as expected:
(zippy '(4 2 6 3 5 1))
=> '(1 6 2 5 3 4)
This R6RS solution does what Chris Jester-Young proposes and it really is how to do it the bad way. BTW Chris' and Óscar's solutions on the same question without sorting is superior to this zippy procedure.
#!r6rs
(import (rnrs base)
(rnrs sorting)) ; list-sort
(define (zippy lis)
(let loop ((count-down (- (length lis) 1))
(count-up 0))
(cond ((> count-up count-down) '())
((= count-up count-down) (cons (list-ref lis count-down) '()))
(else (cons (list-ref lis count-down)
(cons (list-ref lis count-up)
(loop (- count-down 1)
(+ count-up 1))))))))
(define (sort-rearrange lis)
(zippy (list-sort < lis)))
Here is a simple, tail-recursive approach that uses a 'slow/fast' technique to stop the recursion when half the list is traversed:
(define (interleave l)
(let ((l (list-sort < l)))
(let merging ((slow l) (fast l) (revl (reverse l)) (rslt '()))
(cond ((null? fast)
(reverse rslt))
((null? (cdr fast))
(reverse (cons (car slow) rslt)))
(else
(merging (cdr slow) (cddr fast) (cdr revl)
(cons (car revl) (cons (car slow) rslt))))))))
So, you don't mind slow and just want a selection-based approach, eh? Here we go....
First, we define a select1 function that gets the minimum (or maximum) element, followed by all the other elements. For linked lists, this is probably the simplest approach, easier than trying to implement (say) quickselect.
(define (select1 lst cmp?)
(let loop ((seen '())
(rest lst)
(ext #f)
(extseen '()))
(cond ((null? rest)
(cons (car ext) (append-reverse (cdr extseen) (cdr ext))))
((or (not ext) (cmp? (car rest) (car ext)))
(let ((newseen (cons (car rest) seen)))
(loop newseen (cdr rest) rest newseen)))
(else
(loop (cons (car rest) seen) (cdr rest) ext extseen)))))
Now actually do the interweaving:
(define (zippy lst)
(let recur ((lst lst)
(left? #t))
(if (null? lst)
'()
(let ((selected (select1 lst (if left? < >))))
(cons (car selected) (recur (cdr selected) (not left?)))))))
This approach is O(n²), whereas the sort-and-interleave approach recommended by everybody else here is O(n log n).

Partitioning a list in Racket

In an application I'm working on in Racket I need to take a list of numbers and partition the list into sub-lists of consecutive numbers:
(In the actual application, I'll actually be partitioning pairs consisting of a number and some data, but the principle is the same.)
i.e. if my procedure is called chunkify then:
(chunkify '(1 2 3 5 6 7 9 10 11)) -> '((1 2 3) (5 6 7) (9 10 11))
(chunkify '(1 2 3)) -> '((1 2 3))
(chunkify '(1 3 4 5 7 9 10 11 13)) -> '((1) (3 4 5) (7) (9 10 11) (13))
(chunkify '(1)) -> '((1))
(chunkify '()) -> '(())
etc.
I've come up with the following in Racket:
#lang racket
(define (chunkify lst)
(call-with-values
(lambda ()
(for/fold ([chunk '()] [tail '()]) ([cell (reverse lst)])
(cond
[(empty? chunk) (values (cons cell chunk) tail)]
[(equal? (add1 cell) (first chunk)) (values (cons cell chunk) tail)]
[else (values (list cell) (cons chunk tail))])))
cons))
This works just fine, but I'm wondering given the expressiveness of Racket if there isn't a more straightforward simpler way of doing this, some way to get rid of the "call-with-values" and the need to reverse the list in the procedure etc., perhaps some way comepletely different.
My first attempt was based very loosely on a pattern with a collector in "The Little Schemer" and that was even less straightforward than the above:
(define (chunkify-list lst)
(define (lambda-to-chunkify-list chunk) (list chunk))
(let chunkify1 ([list-of-chunks '()]
[lst lst]
[collector lambda-to-chunkify-list])
(cond
[(empty? (rest lst)) (append list-of-chunks (collector (list (first lst))))]
[(equal? (add1 (first lst)) (second lst))
(chunkify1 list-of-chunks (rest lst)
(lambda (chunk) (collector (cons (first lst) chunk))))]
[else
(chunkify1 (append list-of-chunks
(collector (list (first lst)))) (rest lst) list)])))
What I'm looking for is something simple, concise and straightforward.
Here's how I'd do it:
;; chunkify : (listof number) -> (listof (non-empty-listof number))
;; Split list into maximal contiguous segments.
(define (chunkify lst)
(cond [(null? lst) null]
[else (chunkify/chunk (cdr lst) (list (car lst)))]))
;; chunkify/chunk : (listof number) (non-empty-listof number)
;; -> (listof (non-empty-listof number)
;; Continues chunkifying a list, given a partial chunk.
;; rchunk is the prefix of the current chunk seen so far, reversed
(define (chunkify/chunk lst rchunk)
(cond [(and (pair? lst)
(= (car lst) (add1 (car rchunk))))
(chunkify/chunk (cdr lst)
(cons (car lst) rchunk))]
[else (cons (reverse rchunk) (chunkify lst))]))
It disagrees with your final test case, though:
(chunkify '()) -> '() ;; not '(()), as you have
I consider my answer more natural; if you really want the answer to be '(()), then I'd rename chunkify and write a wrapper that handles the empty case specially.
If you prefer to avoid the mutual recursion, you could make the auxiliary function return the leftover list as a second value instead of calling chunkify on it, like so:
;; chunkify : (listof number) -> (listof (non-empty-listof number))
;; Split list into maximal contiguous segments.
(define (chunkify lst)
(cond [(null? lst) null]
[else
(let-values ([(chunk tail) (get-chunk (cdr lst) (list (car lst)))])
(cons chunk (chunkify tail)))]))
;; get-chunk : (listof number) (non-empty-listof number)
;; -> (values (non-empty-listof number) (listof number))
;; Consumes a single chunk, returns chunk and unused tail.
;; rchunk is the prefix of the current chunk seen so far, reversed
(define (get-chunk lst rchunk)
(cond [(and (pair? lst)
(= (car lst) (add1 (car rchunk))))
(get-chunk (cdr lst)
(cons (car lst) rchunk))]
[else (values (reverse rchunk) lst)]))
I can think of a simple, straightforward solution using a single procedure with only primitive list operations and tail recursion (no values, let-values, call-with-values) - and it's pretty efficient. It works with all of your test cases, at the cost of adding a couple of if expressions during initialization for handling the empty list case. It's up to you to decide if this is concise:
(define (chunkify lst)
(let ((lst (reverse lst))) ; it's easier if we reverse the input list first
(let loop ((lst (if (null? lst) '() (cdr lst))) ; list to chunkify
(cur (if (null? lst) '() (list (car lst)))) ; current sub-list
(acc '())) ; accumulated answer
(cond ((null? lst) ; is the input list empty?
(cons cur acc))
((= (add1 (car lst)) (car cur)) ; is this a consecutive number?
(loop (cdr lst) (cons (car lst) cur) acc))
(else ; time to create a new sub-list
(loop (cdr lst) (list (car lst)) (cons cur acc)))))))
Yet another way to do it.
#lang racket
(define (split-between pred xs)
(let loop ([xs xs]
[ys '()]
[xss '()])
(match xs
[(list) (reverse (cons (reverse ys) xss))]
[(list x) (reverse (cons (reverse (cons x ys)) xss))]
[(list x1 x2 more ...) (if (pred x1 x2)
(loop more (list x2) (cons (reverse (cons x1 ys)) xss))
(loop (cons x2 more) (cons x1 ys) xss))])))
(define (consecutive? x y)
(= (+ x 1) y))
(define (group-consecutives xs)
(split-between (λ (x y) (not (consecutive? x y)))
xs))
(group-consecutives '(1 2 3 5 6 7 9 10 11))
(group-consecutives '(1 2 3))
(group-consecutives '(1 3 4 5 7 9 10 11 13))
(group-consecutives '(1))
(group-consecutives '())
I want to play.
At the core this isn't really anything that's much different from what's
been offered but it does put it in terms of the for/fold loop. I've
grown to like the for loops as I think they make for much
more "viewable" (not necessarily readable) code. However, (IMO --
oops) during the early stages of getting comfortable with
racket/scheme I think it's best to stick to recursive expressions.
(define (chunkify lst)
(define-syntax-rule (consecutive? n chunk)
(= (add1 (car chunk)) n))
(if (null? lst)
'special-case:no-chunks
(reverse
(map reverse
(for/fold ([store `((,(car lst)))])
([n (cdr lst)])
(let*([chunk (car store)])
(cond
[(consecutive? n chunk)
(cons (cons n chunk) (cdr store))]
[else
(cons (list n) (cons chunk (cdr store)))])))))))
(for-each
(ƛ (lst)
(printf "input : ~s~n" lst)
(printf "output : ~s~n~n" (chunkify lst)))
'((1 2 3 5 6 7 9 10 11)
(1 2 3)
(1 3 4 5 7 9 10 11 13)
(1)
()))
Here's my version:
(define (chunkify lst)
(let loop ([lst lst] [last #f] [resint '()] [resall '()])
(if (empty? lst)
(append resall (list (reverse resint)))
(begin
(let ([ca (car lst)] [cd (cdr lst)])
(if (or (not last) (= last (sub1 ca)))
(loop cd ca (cons ca resint) resall)
(loop cd ca (list ca) (append resall (list (reverse resint))))))))))
It also works for the last test case.

Resources