Search code examples
listrecursionschememultiplication

Multiplying Elements in a List Containing Pairs


I'm trying to write a code (function) using Scheme that:

  • Takes a list of any size as a parameter
  • Multiplies every number of the list together
  • Symbols should be skipped over
  • Values inside pairs should be included in multiplication

In other words, results should be as follows:

> (mult '(1 2 3))
6
> (mult '(1 2 x 3 4))
24
> (mult '(1 2 z (3 y 4)))
24 (mine gives me 2)

My code allows me to skip over the symbols and multiply everything. However, once I include a pair inside the list, it acts as though it isn't a number, therefore acting like it doesn't exist. Here's my code:

(define mult
       (lambda (x)
               (if (null? x)
                      1
                      (if(number? (car x))
                         (* (car x) (mult (cdr x)))
                         (mult(cdr x))))))

I've tried to use append when it finds a pair, but clearly I did it wrong... Any help on how I could get it to include the values inside a pair would be much appreciated.

i.e. '(1 2 y (3 z 4) = 1 * 2 * 3 * 4


Solution

  • You are nearly there, just missing the list? test:

    (define (mult lst)
      (if (null? lst) 
          1
          (let ((ca (car lst)))
            (cond
              ((number? ca) (* ca (mult (cdr lst))))
              ((list? ca)   (* (mult ca) (mult (cdr lst))))
              (else         (mult (cdr lst)))))))
    

    EDIT

    He're an equivalent version without let:

    (define (mult lst)
      (cond
        ((null? lst)         1)
        ((number? (car lst)) (* (car lst) (mult (cdr lst))))
        ((cons? (car lst))   (* (mult (car lst)) (mult (cdr lst))))
        (else                (mult (cdr lst)))))
    

    As you see, (car lst) is likely to be evaluated more than once, so I used let in the first version to avoid this.