tags:

views:

77

answers:

2

I am trying to write some code that will loop through a list and add like terms. For example if the input was ((2 1) (3 4) (5 3) (2 4)) the the result would be ((2 1) (5 4) (5 3)) but I am having trouble with the code. I'm trying to cons the cdr of the input list to a null list and then just compare the car of the list to the car of the new list and traverse down the list but my code just isn't working. What am I doing wrong here?

  (define loop-add
  (lambda (l temp outputList)
    (if (or (equal? (cdr l) '()) (equal? (pair? (car l)) #f))
        outputList
        (if (equal? l '())
            outputList
            (let ((temp (cdr l)))
              (if (equal? temp '())
                  (loop-add (cdr l) outputList)
                  (if (equal? (cdr (car l)) (cdr (car temp)))
                      (loop-add l (cdr temp) (cons (append (cdr (car l)) (cdr (car (cdr l)))) outputList))
                      (loop-add l temp outputList))))))))

but the problem now is at the end line its just going to be an infinite loop. I need a way to recur with the input list but with temp being the cdr of the previous temp list.

+1  A: 

Start by writing a procedure that can transform your input list into a new list of the unique terms in the original list, so

(get-unique-terms '((2 1) (3 4) (5 3) (2 4)))
(1 4 3) ; or something like that

Call this new list TERMS. Now for each element in TERMS you can search the original list for matching elements, and get a sum of the coefficients:

(define (collect-like-terms l)
  (let ((terms (get-unique-terms l)))
    ;; For each element of TERMS,
    ;;   Find all elements of L which have a matching term,
    ;;      Sum the coefficients of those elements,
    ;;      Make a record of the sum and the term a la L.
    ;; Collect the results into a list and return.
Cirno de Bergerac
That is what I am doing but my trouble is when you go about matching the terms, how do you match the first element of the list to all the elements of the TERMS list? Because I was thinking to just match the first element in all the elements of TERMS then once TERMS hits null just match the cdr of the list to all the terms in TERMS how do you call this method? with one parameter? then just assign a variable to be the TERMS list?
user258875
But how do you loop through a list comparing its first element to every element of another list, thats what my problem is.
user258875
Well, could you loop over a list and compare each element to a hard-coded value?
Cirno de Bergerac
well you would just compare the car of the list to the car of the cdr of the other list. But my problem is when you want to recur how do you only recur over the cdr of the list without having an infinite loop. Ill post my newest code, which is correct I believe but on the last line I need a way to recur because now its only comparing the same list over and over.
user258875
A: 

Here's a simple solution in Racket:

(define (loop-add l)
  (define table
    (for/fold ([h (hash)]) ([i l])
       (dict-update h (cadr i) (lambda (v) (+ v (car i))) 0)))
  (dict-map table (lambda (key val) (list val key))))

(loop-add '((2 1) (3 4) (5 3) (2 4)))
Sam TH