How to Multiply a value to the next value in a list in scheme?

125 views Asked by At

Is there a way to multiply each value in a list, however instead of getting another list (2 4 6) like so, you get the multiplication of all values together.

(define (multi x y)
  (if (null? y)
     '()
     (* x (car y))))
(multi 2 '(1 2 3))
2 * 1 * 2 * 3
==> 6

This may be very simple to some people, but I am having a coding block here, so please don't be rude in the comments. thank you.

3

There are 3 answers

2
PyotrVanNostrand On BEST ANSWER
(define (mult x lst)
  (if (null? lst)
      x
      (mult (* x (car lst))(cdr lst))))
0
alinsoar On

Use fold left or right, using this the system will iterate over the input without building a new list but only changing an accumulator.

(fold-right * 1 '(2 3 4))
(fold-left * 1 '(2 3 4))
0
Dúthomhas On

While fold is the function scheme provides for this kind of operation, it does not help you to understand how to do it yourself.

Lets start with a proper list:

(1 . (2 . (3 . ())))

We wish to multiply all its elements together:

{(1 . (2 . (3 . ())))} => 1 * 2 * 3

The way to think about lists is: If I can do something with the head in relation to the rest of the list, then I can do it to the whole list.

Let’s rewrite that multiplication:

{(1 . (2 . (3 . ())))} => (1 * {(2 . (3 . ()))})
                       => (1 * (2 * {(3 . ())}))
                       => (1 * (2 * (3 * {()})))

We can turn that null into a 1 so that the multiplication works:

{(1 . (2 . (3 . ())))} => (1 * (2 * (3 *  1 )))

Collapsing the sequence gives us:

(1 * (2 * 3))
(1 * 6)
6

Since your function is not expected to take any arguments except the list, write it as such:

(define (multiply-list xs)

Don’t forget to turn the '() into a 1:

  (if (null? xs)
      1

Now we just need to handle the magic recursive part. Remember, if I can do something with the head...

      (* (car xs)

...in relation to the rest — which must be collapsed by multiplying it...

         (multiply-list (cdr xs))

...then you are done!

This assumes that it is valid for (multiply-list '())1.

If it needs to become anything else (such as '() or 0) then you will have to make your recursive part a little more complicated. You will still need to check if the list is null and return the weird value, but then you must also make sure not to invoke recursion if you have reached the end of an initially non-empty list.

(define (multiply-list xs)
  (if (null? xs)
      0  ; or whatever weirdness is required to return if the initial list is empty
      (if (null? (cdr xs))  ; now we only want to recurse if there are more elements in the tail
          dont-recurse-here
          recurse-here)))