0

Doing this in Scheme/Racket

The question is: Take two equal-length lists of numbers, then return a list consisting of the smallest numbers position by position.

Ex: listMins( '(1 7 5) '(2 8 3) )

returns (1, 7, 3) since 1<2 and 7<8 and 3<5

I am new to functional programming and weak at recursion. I feel as though I am just missing some key pieces that I don't know how to tackle in my pseudocode, so that I can start coding this for real. (I tried jumping into code first, and it didn't work, so I'm taking a step back to pseudocode.)

PSEUDOCODE:

(listMins x, y)(
    (if !null A)
        (if > listAitem listBitem)
            (add A to newList) ;where do I make newList?
            (add B to newList)
        (return newList)
)
HC_
  • 1,040
  • 10
  • 23

1 Answers1

8

This is actually extremely easy if you use higher-order functions like map, especially since Scheme's map can accept many arguments, in which case it acts like a "zip" function. This means it's possible to implement your list-mins function in a single, terse line of code:

(define (list-mins . lsts)
  (apply map min lsts))

This uses some relatively complex machinery of Scheme/Racket, though, so it might not be very clear what's going on. The dotted argument, paired with apply allows list-mins to take any number of lists, but you really only need it to accept two, so here's a simpler version:

(define (list-mins a b)
  (map min a b))

What does this do? Well, map iterates over its arguments in parallel, applies a procedure to each set of elements, then produces a new list with the elements of the results. The min function simply returns the minimum of its arguments. To see what this looks like in action, here's what the above code is basically doing:

   (map min '(1 7 5) '(2 8 3))
=> (list (min 1 2)
         (min 7 8)
         (min 5 3))
=> (list 1 7 3)

Of course, it's possible to write this yourself, too, using recursion. Doing it manually would look like this:

(define (list-mins a b)
  (if (empty? a)
      '()
      (cons (min (first a) (first b))
            (list-mins (rest a) (rest b)))))

This is pretty much just unrolling what map does, and using map directly is much more clear (it expresses your intent to iterate over a set of lists), so it would be much more idiomatic than doing the recursion yourself. Still, if you're learning, then the explicit version might be more clear.

Alexis King
  • 43,109
  • 15
  • 131
  • 205
  • Extremely, extremely helpful.. I somehow was so tunnel visioned on the `car` and `cdr` part of my notes that I missed `map` entirely... definitely helps make this a lot quicker it seems. Thanks a lot for expanding the map min into the actual steps its doing.. that was very helpful. I was initially so confused on how to return a new array in the "middle" of a function.. and on the next problem I'm working on, I still am to some degree but I'm going to try at least another hour and a half on it.. Thanks again! – HC_ Nov 05 '15 at 22:28