views:

219

answers:

1

I need to write a program for equivalence classes and get this outputs...

(equiv '((a b) (a c) (d e) (e f) (c g) (g h))) 
 => ((a b c g h) (d e f))

(equiv '((a b) (c d) (e f) (f g) (a e)))
 => ((a b e f g) (c d))

Basically, A set is a list in which the order doesn't matter, but elements don't appear more than once. The function should accept a list of pairs (elements which are related according to some equivalence relation), and return a set of equivalence classes without using iteration or assignment statements (e.g. do, set!, etc.).

However, set utilities such as set-intersection, set-union and a function which eliminates duplicates in a list and built-in functions union, intersection, and remove-duplicates are allowed.

Thanks a lot!

By the way, It's not a homework question. A friend of mine need this piece of code to solve smilar questions.

+3  A: 

That sounds like a typical homework question.

It's not that difficult, though.

A simple recursive function over the input list will do. The ingredients of the function are already mentioned in the task description: simple set operations.

If it is homework, then this applies: The typical strategy for homework questions is that YOU have to show first your solution attempt. That should be at least a mostly correct formulation of the algorithm or almost working code. Then Lispers may help you with the finishing touches...

Well, time passes and no solution.

So here is one using Common Lisp:

We need three functions.

The first function adds a single pair to the set of pairs. A pair is a list. The set of pairs is a list of pairs. For the pair we compute two sets: the set of pairs that are equivalent and the set of pairs that are not equivalent. We combine the pairs that are equivalent with our in input pair into a single set.

(defun equiv-add (e l)
  (let ((l- (remove-if     (lambda (i) (intersection e i)) l))
        (l+ (remove-if-not (lambda (i) (intersection e i)) l)))
    (cons (remove-duplicates (reduce #'union (cons e l+)))
          l-)))

The second function adds each pair of a set of pairs to the result. It adds them by calling EQUIV-ADD.

(defun equiv-aux (list result)
  (if (null list)
      result
    (equiv-aux (rest list)
               (equiv-add (first list)
                          result))))

The third function just calls EQUIV-AUX with the input set and an empty result. Additionally it sorts the result sublists.

(defun equiv (list)
  (mapcar (lambda (el)
            (sort el #'string-lessp))
          (equiv-aux list '())))

Example calls:

CL-USER 34 > (equiv '((a b) (c d) (e f) (f g) (a e)))
((A B E F G) (C D))

CL-USER 35 > (equiv '((a b) (a c) (d e) (e f) (c g) (g h))) 
((A B C G H) (D E F))
Rainer Joswig