Question

I am not too proficient with functional style and I don't want to use any set functions, so I have a problem. I am really struggling whether I should do recursively or in a different manner.

I have a collection of pairs in a list, like so:

((4 2) (3 1) (3 2) (2 4) etc...)

In this pair '(4 2), the second element '2' tells me which other pairs it matches to, in this case '(3 2). So, I add these two pairs together using their first element, in this case, it's '4' and '3'. The new pair is now '(7 2). And so on for other pairs in the list too. Finally, it should return:

 ((7 2) (3 1) (2 4))

I would care less about the order. . I already have a working function that add two different pairs. The only assumption with this function is that the pairs are matching.

Consequently, what I want to do is manipulated this list of pairs to return a list in these manners.

Examples:

 take the list ((4 2) (3 1) (3 2) (2 4))    
 matching-pairs: '(4 2) and '(3 2)

 and then return --> ((7 2) (3 1) (2 4))


 take the list ((2 1) (3 2) (1 2) (5 1) (6 3))
 matching-pairs: '(2 1) and '(5 1)
                 '(3 2) and '(1 2)

 and then return --> ((7 1) (4 2) (6 3))

Thank you for your time and efforts.

Was it helpful?

Solution

Iterate over your list and store each pair's car into a list in an assoc that looks like this:

original: ((2 . 1) (3 . 2) (1 . 2) (5 . 1) (6 . 3))
new:      ((1 . (2 5))
           (2 . (3 1))
           (3 . (6))

Then sum together all the cdrs and flip each pair to get this:

          ((7 . 1) (4 . 2) (6 . 3))

OTHER TIPS

(defun get-pairs (alist index)
  (cond
   (alist
    (if (= (nth 1 (car alist)) index)
       (append (list (caar alist)) (get-pairs (cdr alist) index))
       (get-pairs (cdr alist) index)))
  ((not alist)
   'nil)))


(defun get-iterator (alist)
  (labels
    ((f (alist res)
        (cond
          (alist
            (if (member (nth 1 (car alist)) res)
              (f (cdr alist) res)
              (f (cdr alist) (append (cdar alist) res))))
          ((not alist)
            res))))
    (f alist 'nil)))


(defun get-value (alist)
  (loop for i in (get-iterator alist)
        collect (get-pairs alist i)))

(defun list-sum (alist)
  (loop for i in (get-value alist)
        collect (apply #'+ i)))

(defun match-value (alist)
  (loop for i in (get-iterator alist)
        for j in (list-sum alist)
        collect (append (list j) (list i))))


(defparameter *my-list* '((2 1) (3 1) (4 2) (5 2) (8 1) (9 2) (1 3) (0 3)))

(print (match-value *my-list*))

Sorry for the messy code but that should do the trick if I understood the problem right.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top