listschemeracketbag

How can I remove all the elements that are in the second list in racket?


For Example, if the first bag has '(a b a a) and the second bag has '(a b c), it should return '(a a)

This function should return a list(bag) where each element appears as many times as it appears in the first bag, minus the number of times it appears in the second bag (but never less than 0 times). For example:

 (difference '(a a b a) '(b a a)) --->'(a)
 (difference '(a b c) '(a b a a)) --->'(c)
 (difference '(a b c) '(a b c)) --->'()
 (difference '() '(a b a a)) --->'()
 (difference '(a b a a) '())--->'(b a a a)

Here is what I have in racket:

(define (difference L1 L2)
  (cond
    [(null? L1) '()]
    [(null? L2) L1]
    [(equal? L1 L2)'()]
    [(not(null? L2))(remove (car L2) L1)]
    [(difference L1 (cdr L2))]
    ))

My code will only remove the first element in L2. How can I fix my code to remove all the elements that are in L2?

My output:

 (difference '(a a b a) '(b a a)) --->'(a a a)
 (difference '(a b c) '(a b a a)) --->'(b c)
 (difference '(a b c) '(a b c)) --->'()
 (difference '() '(a b a a)) --->'()
 (difference '(a b a a) '())--->'(b a a a)

Solution

  • Note that your recursion, (difference L1 (cdr L2)), is the last condition.
    You will never reach it because the earlier conditions cover all possible situations – the two conditions (null? L2) and (not (null? L2)) are mutually exclusive, so one of them must be true. Also, it has no corresponding result, but you don't notice that because you never reach it.

    Your first two case are fine:

    (define (difference L1 L2)
      (cond
        [(null? L1) '()]
        [(null? L2) L1]
    

    but then there's really only one case left – neither list is empty – and that condition is

        [else
    

    and here you want to

    1. remove all the occurrences of (car L2) from L1
    2. produce the difference between that list and (cdr L2)

    which is

    (difference (remove (car L2) L1) (cdr L2))