Creating binary tree using Racket - binary-tree

'(6 (3 (2) (5)) (7 () (9))) is a sorted binary tree
Write a recursive function tree-insert that takes a tree and a number and returns the tree with the number inserted.
(tree-insert 8 '()) should return ‘(8)
(tree-insert 5 ‘(8)) should return ‘(8 (5))
(tree-insert 3 '(6 () (7))) should return '(6 (3) (7))
(tree-insert 4 '(6 (3) (7))) should return '(6 (3 () (4)) (7))

The first thing to do when dealing with a problem like this is to realise that programming as if conses were all there is is not a good idea: it makes for code which is hard to understand and hard to write. You are processing a sorted binary tree which happens to be represented as a tree of conses. So first of all write some abstractions. Unfortunately the representation of the tree is kind of irregular: (9) is the same as (9 ()) is the same as (9 () ()), and the question wants you to return the shortest version, so the abstractions need to cope with that.
Empty nodes, and the value of a node are easy:
(define empty-node '())
(define empty-node? null?)
(define node-value car)
getting the left and right elements of a node are fiddly and I have used Racket's nice match facility for this:
(define (node-left node)
(match node
[(or (list _ l)
(list _ l _))
l]
[(list _)
empty-node]))
(define (node-right node)
(match node
[(list _ _ r)
r]
[(or (list _ _)
(list _))
empty-node]))
And finally making a node also needs to deal with the annoying shorthand versions of nodes with empty children:
(define (make-node value (left empty-node) (right empty-node))
(if (empty-node? right)
(if (empty-node? left)
(list value)
(list value left))
(list value left right)))
Once we have these abstractions, then tree-insert becomes essentially trivial to write:
(define (tree-insert n node)
(cond
[(empty-node? node)
(make-node n)]
[(< n (node-value node))
(make-node (node-value node)
(tree-insert n (node-left node))
(node-right node))]
[else
(make-node (node-value node)
(node-left node)
(tree-insert n (node-right node)))]))

The design recipe for functions is:
data definition
stub, signature, purpose
examples/unit tests
template, plan
function definition, testing
From the example binary tree:
'(6 (3 (2) (5)) (7 () (9))) #| 6
/ \
3 \
/ \ \
2 5 7
/ \
9 |#
one could deduce the data definition:
a TreeOfNumber is one of:
- empty
- (list Number TreeOfNumber TreeOfNumber)
where all numbers in first TreeOfNumber <= Number, all in second >
A first example/test could be:
(check-expect (tree-insert 8 '()) '(8 () ()))
and stub with signature and purpose:
(define (tree-insert n ton) ;; Number TreeOfNumber -> TreeOfNumber
;; produce ton with n inserted at correct place
(list n '() '()))
So the function will have the form:
(define (tree-insert n ton) ;; Number TreeOfNumber -> TreeOfNumber
;; produce ton with n inserted at correct place
(cond
[(empty? ton) (list n '() '()) ]
[else ... (list ... ) ]))
Two more examples:
(check-expect (tree-insert 6 '(8 () ())) '(8 (6 () ()) () ) )
(check-expect (tree-insert 10 '(8 () ())) '(8 () (10 () ())) )
can be rewritten as:
(check-expect (tree-insert 6 '(8 () ())) (list 8 (tree-insert 6 '()) '() ) )
(check-expect (tree-insert 10 '(8 () ())) (list 8 '() (tree-insert 10 '()) ) )
which suggests how to complete the definition:
(define (tree-insert n ton) ;; Number TreeOfNumber -> TreeOfNumber
;; produce ton with n inserted at correct place
(cond
[(empty? ton) (list n '() '()) ]
[else
(if (<= n (first ton))
(list (first ton) (tree-insert n (second ton)) (third ton))
(list (first ton) (second ton) (tree-insert n (third ton)))) ]))
A few more tests:
(check-expect (tree-insert 5 '(8 (6 () ()) ())) '(8 (6 (5 () ()) ()) ()) )
(check-expect (tree-insert 6 '(8 (6 () ()) ())) '(8 (6 (6 () ()) ()) ()) )
(check-expect (tree-insert 7 '(8 (6 () ()) ())) '(8 (6 () (7 () ())) ()) )
(check-expect (tree-insert 8 '(8 (6 () ()) ())) '(8 (6 () (8 () ())) ()) )
(check-expect (tree-insert 9 '(8 (6 () ()) ())) '(8 (6 () ()) (9 () ())) )
But other examples in the question omit trailing empty trees,
so introduce a function to strip them:
(define (tree-trim ton) ;; TreeOfNumber -> TrimmedTree
;; produce ton with trailing emptys dropped
(cond
[(empty? ton) empty ]
[(and (empty? (second ton)) (empty? (third ton)))
(list (first ton)) ]
[(empty? (third ton))
(list (first ton) (tree-trim (second ton))) ]
[else
(list (first ton) (tree-trim (second ton)) (tree-trim (third ton))) ]))
(check-expect (tree-trim '(8 (6 () (7 () ())) ())) '(8 (6 () (7))) )
tree-insert could be wrapped by tree-trim to produce the examples in the question;
as another example of combining these functions, one could have:
(define (tree-insert-list lon ton) ;; ListOfNumber TreeOfNumber -> TrimmedTree
;; produce ton with elements of lon inserted, trailing emptys dropped
(cond
[(empty? lon) (tree-trim ton) ]
[else
(tree-insert-list (cdr lon) (tree-insert (car lon) ton)) ]))
(check-expect
(tree-insert-list '(22 25 7 16 8 34 67 7 32 17 8 4 5 3) '())
'(22 (7 (7 (4 (3) (5))) (16 (8 (8)) (17))) (25 () (34 (32) (67)))) )
Welcome to DrRacket, version 8.6 [cs].
Language: Beginning Student with List Abbreviations; memory limit: 128 MB.
All 12 tests passed!
>

(define (tree-insert element tree)
(cond ((empty? tree) (list element))
((and (>= element (car tree)) (empty? (cdr tree)))
(list (car tree) '() (list element)))
((>= element (car tree))
(list (car tree) (cadr tree) (tree-insert (caddr tree) element)))
((empty? (cdr tree))
(list (car tree) (list element)))
(else
(list (car tree) (tree-insert element (cadr tree)) (caddr tree)))))
> (tree-insert 8 '())
'(8)
> (tree-insert 5 '(8))
'(8 (5))
> (tree-insert 3 '(6 () (7)))
'(6 (3) (7))
> (tree-insert 4 '(6 (3) (7)))
'(6 (3 () (4)) (7))

Related

Scheme recursive

Deos anyone know, how I can make this funktion recursive by inserting the function somewhere? I am not allowed to use implemented functions for lists except append, make-pair(list) and reverse.
(: split-list ((list-of %a) -> (tuple-of (list-of %a) (list-of %a))))
(check-expect (split-list (list 1 2)) (make-tuple (list 1) (list 2)))
(check-expect (split-list (list 1 2 3 4)) (make-tuple (list 1 3) (list 2 4)))
(check-expect (split-list (list 1 2 3)) (make-tuple (list 1 3) (list 2)))
(check-expect (split-list (list 1 2 3 4 5)) (make-tuple (list 1 3 5) (list 2 4)))
(check-expect (split-list (list 1 2 3 4 5 6)) (make-tuple (list 1 3 5) (list 2 4 6)))
(define split-list
(lambda (x)
(match x
(empty empty)
((make-pair a empty) (make-tuple a empty))
((make-pair a (make-pair b empty)) (make-tuple (list a) (list b)))
((make-pair a (make-pair b c)) (make-tuple (list a (first c)) (list b (first(rest c))))))))
Code for make-tuple:
(define-record-procedures-parametric tuple tuple-of
make-tuple
tuple?
(first-tuple
rest-tuple))
Here's a way you can fix it using match and a named let, seen below as loop.
(define (split xs)
(let loop ((xs xs) ;; the list, initialized with our input
(l empty) ;; "left" accumulator, initialized with an empty list
(r empty)) ;; "right" accumulator, initialized with an empty list
(match xs
((list a b rest ...) ;; at least two elements
(loop rest
(cons a l)
(cons b r)))
((cons a empty) ;; one element
(loop empty
(cons a l)
r))
(else ;; zero elements
(list (reverse l)
(reverse r))))))
Above we use a loop to build up left and right lists then we use reverse to return the final answer. We can avoid having to reverse the answer if we build the answer in reverse order! The technique used here is called continuation passing style.
(define (split xs (then list))
(match xs
((list a b rest ...) ;; at least two elements
(split rest
(λ (l r)
(then (cons a l)
(cons b r)))))
((cons a empty) ;; only one element
(then (list a) empty))
(else ;; zero elements
(then empty empty))))
Both implementations perform to specification.
(split '())
;; => '(() ())
(split '(1))
;; => '((1) ())
(split '(1 2 3 4 5 6 7))
;; => '((1 3 5 7) (2 4 6))
Grouping the result in a list is an intuitive default, but it's probable that you plan to do something with the separate parts anyway
(define my-list '(1 2 3 4 5 6 7))
(let* ((result (split my-list)) ;; split the list into parts
(l (car result)) ;; get the "left" part
(r (cadr result))) ;; get the "right" part
(printf "odds: ~a, evens: ~a~n" l r))
;; odds: (1 3 5 7), evens: (2 4 6)
Above, continuation passing style gives us unique control over the returned result. The continuation is configurable at the call site, using a second parameter.
(split '(1 2 3 4 5 6 7) list) ;; same as default
;; '((1 3 5 7) (2 4 6))
(split '(1 2 3 4 5 6 7) cons)
;; '((1 3 5 7) 2 4 6)
(split '(1 2 3 4 5 6 7)
(λ (l r)
(printf "odds: ~a, evens: ~a~n" l r)))
;; odds: (1 3 5 7), evens: (2 4 6)
(split '(1 2 3 4 5 6 7)
(curry printf "odds: ~a, evens: ~a~n"))
;; odds: (1 3 5 7), evens: (2 4 6)
Oscar's answer using an auxiliary helper function or the first implementation in this post using loop are practical and idiomatic programs. Continuation passing style is a nice academic exercise, but I only demonstrated it here because it shows how to step around two complex tasks:
building up an output list without having to reverse it
returning multiple values
I don't have access to the definitions of make-pair and make-tuple that you're using. I can think of a recursive algorithm in terms of Scheme lists, it should be easy to adapt this to your requirements, just use make-tuple in place of list, make-pair in place of cons and make the necessary adjustments:
(define (split lst l1 l2)
(cond ((empty? lst) ; end of list with even number of elements
(list (reverse l1) (reverse l2))) ; return solution
((empty? (rest lst)) ; end of list with odd number of elements
(list (reverse (cons (first lst) l1)) (reverse l2))) ; return solution
(else ; advance two elements at a time, build two separate lists
(split (rest (rest lst)) (cons (first lst) l1) (cons (second lst) l2)))))
(define (split-list lst)
; call helper procedure with initial values
(split lst '() '()))
For example:
(split-list '(1 2))
=> '((1) (2))
(split-list '(1 2 3 4))
=> '((1 3) (2 4))
(split-list '(1 2 3))
=> '((1 3) (2))
(split-list '(1 2 3 4 5))
=> '((1 3 5) (2 4))
(split-list '(1 2 3 4 5 6))
=> '((1 3 5) (2 4 6))
split is kind of a de-interleave function. In many other languages, split names functions which create sublists/subsequences of a list/sequence which preserve the actual order. That is why I don't like to name this function split, because it changes the order of elements in some way.
Tail-call-rescursive solution
(define de-interleave (l (acc '(() ())))
(cond ((null? l) (map reverse acc)) ; reverse each inner list
((= (length l) 1)
(de-interleave '() (list (cons (first l) (first acc))
(second acc))))
(else
(de-interleave (cddr l) (list (cons (first l) (first acc))
(cons (second l) (second acc)))))))
You seem to be using the module deinprogramm/DMdA-vanilla.
The simplest way is to match the current state of the list and call it again with the rest:
(define split-list
(lambda (x)
(match x
;the result should always be a tuple
(empty (make-tuple empty empty))
((list a) (make-tuple (list a) empty))
((list a b) (make-tuple (list a) (list b)))
;call split-list with the remaining elements, then insert the first two elements to each list in the tuple
((make-pair a (make-pair b c))
((lambda (t)
(make-tuple (make-pair a (first-tuple t))
(make-pair b (rest-tuple t))))
(split-list c))))))

Scheme Double All List Values and Write Mapping Function

I have a question on a homework assignment that is as follows:
I have the first part (double-list-elements) complete
(define (double-list-elements s)
(if (null? s)
'()
(cons (* 2 (car s))
(double-list-elements (cdr s)))))
but I honestly have absolutely no idea how to proceed with double-list-elements-one. Any pointers would be greatly appreciated.
Close But No Cigar:
(define (double-list-elements s)
(if (null? s)
'()
(cons (* 2 (car s))
(double-list-elements (cdr s)))))
(define (custom-map proc lst)
(if (null? lst)
'()
(cons (proc lst)
(custom-map proc (cdr lst)))))
(define (double-list-elements-one func s)
(custom-map double-list-elements s))
(double-list-elements-one double-list-elements '(1 2 3 4 5 6))
Output = (list (list 2 4 6 8 10 12) (list 4 6 8 10 12) (list 6 8 10 12) (list 8 10 12) (list 10 12) (list 12))
I need to pass double-list-elements to double-list-elements-one as a parameter as well as the list.
You just have to write your own map, it's very very similar to what you already have, simply pass the part that changes as a procedure parameter, and invoke it on the right place:
(define (mymap proc lst)
(if (null? lst)
'()
(cons <invoke proc on current element>
(mymap proc (cdr lst)))))
(define (double-list-elements-one s)
(mymap <pass a proper lambda> s))
(double-list-elements-one '(1 2 3 4 5))
=> '(2 4 6 8 10)

Removing elements within sublists

I have a list of the form:
((1 (3 2 4)) (2 (3 1)) (3 (2 1)) (4 (1)))
This list represents a graph of the form("node" ("edges")). How might I approach writing a procedure that takes a value representing an node, for example "1", and removes that node from the graph. For example: (delete-node n g) with input 5 and '((1 (3 2)) (2 (3 1)) (3 (2 1)) (4 (5)) (5 (4))) should output:
((1 (3 2)) (2 (3 1)) (3 (2 1)) (4 ()))
As can be observed from the example above, the node and any edges added to that node must both be removed. My code thus far is as follows:
(define graph '((1 (3 2)) (2 (3 1)) (3 (2 1)) (4 (5)) (5 (4))))
;...Other procedures not shown...
(define (delete-node n g)
(define (delete ls item)
(cond ((null? ls) nil)
((pair? (car ls))
(cons (delete (car ls) item) (delete (cdr ls) item)))
((equal? (car ls) item) (delete (cdr ls) item))
(else (cons (car ls) (delete (cdr ls) item)))))
(delete (filter (lambda (x) (not (eq? (car x) n))) g) n))
(delete-node 5 graph)
The above code works, but is there a more efficient way of doing this?
A possible definition using high-level functions is the following:
(define (delete-node n g)
(map (lambda(x) (list (car x) (filter (lambda(x) (not (= x n))) (cadr x))))
(filter (lambda(x) (not (= (car x) n))) g)))
(delete-node 5 '((1 (3 2)) (2 (3 1)) (3 (2 1)) (4 (5)) (5 (4))))
; produces ((1 (3 2)) (2 (3 1)) (3 (2 1)) (4 ()))
A slightly more efficient solution with a recursive function is instead the following:
(define (delete-node n g)
(cond ((null? g) '())
((= (caar g) n) (delete-node n (cdr g)))
(else (cons (list (caar g) (filter (lambda(x) (not (= x n))) (cadar g)))
(delete-node n (cdr g))))))
If the graph is large and you know that its structure is correct,
knowing that only one outgoing arc from a node can be equal to n, a more efficient version could be the following:
(define (delete-node n g)
(define (delete-edge edges)
(cond ((null? edges) '())
((= (car edges) n) (cdr edges)) ; stop recursion when the edge is found
(else (delete-edge (cdr edges)))))
(cond ((null? g) '())
((= (caar g) n) (delete-node n (cdr g)))
(else (if (member n (cadar g) =)
(cons (list (caar g) (delete-edge (cadar g)))
(delete-node n (cdr g)))
(cons (car g) (delete-node n (cdr g)))))))
Note that the test (member n (cadar g) =) is done to avoid copying the list of edges when n is not present.
Not sure whether I understand your question correctly - does this match your needs?
(define (delete-node node graph)
(define node-1 (car node))
(define node-2 (cdr node))
(let iter ((graph graph) (result '()))
(if (null? graph)
(reverse result)
(let* ((head (car graph)) (head-1 (car head)) (head-2 (cadr head)))
(iter (cdr graph)
(cons (cond
((eqv? head-1 node-1) (list head-1 (remove node-2 head-2)))
((eqv? head-1 node-2) (list head-1 (remove node-1 head-2)))
(else head))
result))))))
Testing:
> (delete-node '(2 . 3) '((1 (3 2 4)) (2 (3 1)) (3 (2 1)) (4 (1))))
'((1 (3 2 4)) (2 (1)) (3 (1)) (4 (1)))
> (delete-node '(1 . 2) '((1 (3 2 4)) (2 (3 1)) (3 (2 1)) (4 (1))))
'((1 (3 4)) (2 (3)) (3 (2 1)) (4 (1)))

Why is my scheme program not combining my two list correctly at the end?

(define unzip (lambda (l)
(define front (lambda (a)
(if (null? a)
'()
(cons (car (car a)) (unzip (cdr a)))
)))
(define back (lambda (b)
(if (null? b)
'()
(cons (car (cdr (car b))) (unzip (cdr b)))
)))
(list (front l) (back l))))
(unzip '((1 2) (3 4) (5 6)))
this call is supposed to return ((1 3 5) (2 4 6))
and if I replace the last line of code "(list (front l) (back l)) with just (front l) or (back l) i get the correct lists but i cant seem to put them together it justs keeps spitting out weird outputs every time i try.
Your code structure is very unconventional and I suspect you're rather new to scheme/racket. Your procedure can be written in a much more idiomatic way.
The first criticism I'd probably make about your code is that it makes the assumption that the lists you're unzipping will only have 2 elements each.
What about unzipping 3 lists of 5 elements or 5 lists of 3 elements ?
What about unzipping 4 lists of 4 elemens ?
What about unzipping 1 list of 7 elements or 7 lists of 1 element ?
What about unzipping nothing ?
These questions all point to a fundamental concept that helps shape well-structured procedures:
"What is a "total" procedure ?"
A total procedure is one that is defined for all values of an accepted type. What that means to us is that, if we write an unzip procedure, it should
accept an empty list
accept any number of lists
accept lists of any length1
Let's take a look at an unzip procedure that does that now. It's likely this procedure can be improved, but at the very least, it's easy to read and comprehend
(define (unzip xs (ys empty))
; if no xs are given, return ys
(cond [(empty? xs) empty]
; if the first input is empty, return the final answer; reversed
[(empty? (car xs)) (reverse ys)]
; otherwise, unzip the tail of each xs, and attach each head to ys
[else (unzip (map cdr xs) (cons (map car xs) ys))]))
(unzip '((1 2) (3 4) (5 6)))
; => '((1 3 5) (2 4 6))
Let's step through the evaluation.
; initial call
(unzip '((1 2) (3 4) (5 6)))
; (empty? xs) nope
; (empty? (car xs)) nope
; (unzip (map cdr xs) (cons (map car xs) ys))
; substitue values
(unzip (map cdr '((1 2) (3 4) (5 6)))
(cons (map car '((1 2) (3 4) (5 6))) empty))
; eval (map cdr xs)
(unzip '((2) (4) (6))
(cons (map car '((1 2) (3 4) (5 6))) empty))
; eval (map car xs)
(unzip '((2) (4) (6))
(cons '(1 3 5) empty))
; eval cons
; then recurse unzip
(unzip '((2) (4) (6))
'((1 3 5)))
; (empty? xs) nope
; (empty? (car xs)) nope
; (unzip (map cdr xs) (cons (map car xs) ys))
; substitue values
(unzip (map cdr '((2) (4) (6)))
(cons (map car '((2) (4) (6))) '((1 3 5))))
; eval (map cdr xs)
(unzip '(() () ())
(cons (map car '((2) (4) (6))) '((1 3 5))))
; eval (map car xs)
(unzip '(() () ())
(cons '(2 4 5) '((1 3 5))))
; eval cons
; then recurse
(unzip '(() () ())
'((2 4 5) (1 3 5)))
; (empty? xs) nope
; (empty? (car xs)) yup!
; (reverse ys)
; substituion
(reverse '((2 4 5) (1 3 5)))
; return
'((1 3 5) (2 4 5))
Here's another thing to think about. Did you notice that unzip is basically doing the same thing as zip ? Let's look at your input little closer
'((1 2)
(3 4)
(5 6))
^ ^
Look at the columns. If we were to zip these, we'd get
'((1 3 5) (2 4 6))
"Wait, so do you mean that a unzip is just another zip and vice versa ?"
Yup.
(unzip '((1 2) (3 4) (5 6)))
; => '((1 3 5) (2 4 6))
(unzip (unzip '((1 2) (3 4) (5 6))))
; '((1 2) (3 4) (5 6))
(unzip (unzip (unzip '((1 2) (3 4) (5 6)))))
; '((1 3 5) (2 4 6))
Knowing this, if you already had a zip procedure, your definition to unzip becomes insanely easy
(define unzip zip)
Which basically means:
You don't need an unzip procedure, just re-zip it
(zip '((1 2) (3 4) (5 6)))
; => '((1 3 5) (2 4 6))
(zip (zip '((1 2) (3 4) (5 6))))
; '((1 2) (3 4) (5 6))
(zip (zip (zip '((1 2) (3 4) (5 6)))))
; '((1 3 5) (2 4 6))
Anyway, I'm guessing your unzip procedure implementation is a bit of homework. The long answer your professor is expecting is probably something along the lines of the procedure I originally provided. The sneaky answer is (define unzip zip)
"So is this unzip procedure considered a total procedure ?"
What about unzipping 3 lists of 5 elements or 5 lists of 3 elements ?
(unzip '((a b c d e) (f g h i j) (k l m n o p)))
; => '((a f k) (b g l) (c h m) (d i n) (e j o))
(unzip '((a b c) (d e f) (g h i) (k l m) (n o p)))
; => '((a d g k n) (b e h l o) (c f i m p))
What about unzipping 4 lists of 4 elemens ?
(unzip '((a b c d) (e f g h) (i j k l) (m n o p)))
; => '((a e i m) (b f j n) (c g k o) (d h l p))
What about unzipping 1 list of 7 elements or 7 lists of 1 element ?
(unzip '((a b c d e f g)))
; => '((a) (b) (c) (d) (e) (f) (g))
(unzip '((a) (b) (c) (d) (e) (f) (g)))
; => '((a b c d e f g))
What about unzipping nothing ?
(unzip '())
; => '()
What about unzipping 3 empty lists ?
(unzip '(() () ()))
; => '()
1 We said that unzip should "accept lists of any length" but we're bending the rules just a little bit here. It's true that unzip accepts lists of any length, but it's also true that each list much be the same length as the others. For lists of varying length, an objective "correct" solution is not possible and for this lesson, we'll leave the behavior for mixed-length lists as undefined.
; mixed length input is undefined
(unzip '((a) (b c d) (e f))) ; => ???
A couple side notes
Things like
(car (car x))
(car (cdr (car x)))
Can be simplified to
(caar x)
(cadar x)
The following pair accessor short-hand procedures exist
caar ; (car (car x))
cadr ; (car (cdr x))
cdar ; (cdr (car x))
cddr ; (cdr (cdr x))
caaar ; (car (car (car x)))
caadr ; (car (car (cdr x)))
cadar ; (car (cdr (car x)))
caddr ; (car (cdr (cdr x)))
cdaar ; (cdr (car (car x)))
cdadr ; (cdr (car (cdr x)))
cddar ; (cdr (cdr (car x)))
cdddr ; (cdr (cdr (cdr x)))
caaaar ; (car (car (car (car x))))
caaadr ; (car (car (car (cdr x))))
caadar ; (car (car (cdr (car x))))
caaddr ; (car (car (cdr (cdr x))))
cadaar ; (car (cdr (car (car x))))
cadadr ; (car (cdr (car (cdr x))))
caddar ; (car (cdr (cdr (car x))))
cadddr ; (car (cdr (cdr (cdr x))))
cdaaar ; (cdr (car (car (car x))))
cdaadr ; (cdr (car (car (cdr x))))
cdadar ; (cdr (car (cdr (car x))))
cdaddr ; (cdr (car (cdr (cdr x))))
cddaar ; (cdr (cdr (car (car x))))
cddadr ; (cdr (cdr (car (cdr x))))
cdddar ; (cdr (cdr (cdr (car x))))
cddddr ; (cdr (cdr (cdr (cdr x))))
It is combining the lists correctly, but it's not combining the correct lists.
Extracting the local definitions makes them testable in isolation:
(define (front a)
(if (null? a)
'()
(cons (car (car a)) (unzip (cdr a)))))
(define (back b)
(if (null? b)
'()
(cons (car (cdr (car b))) (unzip (cdr b)))))
(define (unzip l)
(list (front l) (back l)))
(define test '((1 2) (3 4) (5 6)))
Test:
> (front test)
'(1 (3 (5 () ()) (6 () ())) (4 (5 () ()) (6 () ())))
> (front '((1 2)))
'(1 () ())
> (back '((1 2)))
'(2 () ())
Weird...
> (unzip '())
'(() ())
> (unzip '((1 2)))
'((1 () ()) (2 () ()))
It looks like something is correct, but the lists' tails are wrong.
If you look carefully at the definitions of front and back, they're recursing to unzip.
But they should recurse to themselves - front is the "first first" followed by the rest of the "firsts", and back is the "first second" followed by the rest of the "seconds".
unzip has nothing to do with this.
(define (front a)
(if (null? a)
'()
(cons (car (car a)) (front (cdr a)))))
(define (back b)
(if (null? b)
'()
(cons (car (cdr (car b))) (back (cdr b)))))
And now...
> (front test)
'(1 3 5)
> (back test)
'(2 4 6)
> (unzip test)
'((1 3 5) (2 4 6))

Output Elements in List That Are Not Incommon

I've created a function that should return the elements that the two lists do not have in common. Currently, they are outputting exactly what is passed into it. Any suggestions on how to fix this?
(define (findDifference lst1 lst2)
(if (null? lst1) lst2
(cons (car lst1) (findDifference (cdr lst1) lst2))))
(findDifference '(2 3 4 (2 3) 2 (4 5)) '(2 4 (4 5))
Current Output: (2 3 4 (2 3) 2 (4 5) 2 4 (4 5))
Desired Output: (3 (2 3))
You're asking for the symmetric difference of two lists. Try this:
(define (diff list1 list2)
(union (complement list1 list2)
(complement list2 list1)))
Using the following helper procedures:
(define (union list1 list2)
(cond ((null? list1) list2)
((member (car list1) list2) (union (cdr list1) list2))
(else (cons (car list1) (union (cdr list1) list2)))))
(define (complement list1 list2)
(cond ((null? list1) '())
((member (car list1) list2) (complement (cdr list1) list2))
(else (cons (car list1) (complement (cdr list1) list2)))))
Also notice that if you're using Racket you can simply use the built-in set-symmetric-difference procedure for the same effect. For example:
(diff '(2 3 4 (2 3) 2 (4 5)) '(2 4 (4 5)))
=> '(3 (2 3))
Since it seems like homework and I do not want to spoil the fun, here is the brute force algorithm, with some bits left out. If you are really stuck I will give you the full source.
(define (sym-diff xs ys)
;; Since we have the helper function we can determine all the elements that are in the first list,
;; but not in the second list.
;; Then we can pass this intermediate result to the second call to sym-diff-helper.
;;This will return us all the elements that are in the second list but not the first.
(let ((in-first-not-second ...))
(sym-diff-helper ys xs in-first-not-second)))
;; This function will return all the elements from the first list that are not in the second list!
(define (sym-diff-helper xs ys acc)
(cond
;; If the first list is empty we have checked it.
(...
acc)
;; If the first list is not empty yet, check if the first element
;; is in the second list.
;; If so, discard it and continue with the rest of the list.
((member ... ...)
(sym-diff-helper ... ... ...)
;; If the first element of the first list is not in the second list,
;; add it to the accumulator and continue with the rest of the list.
(else
(sym-diff-helper ... ... ...)))
(sym-diff-helper '(1 2 3) '(2 3 4) '())
;; == (1)
(sym-diff-helper '(1 2 (3 4) 5) '(2 3 4) '())
;; == (5 (3 4) 1)
(sym-diff '(2 3 4 (2 3) 2 (4 5)) '(2 4 (4 5)))
;; == ((2 3) 3)
Note that I have chosen to use member. There are a few other search functions but they were not well suited in this case. Hence, I left it there. More info on the search functions can be found here: http://docs.racket-lang.org/reference/pairs.html#%28part..List.Searching%29

Resources