1

Let's assume we have a group of values, if we pass the values in as arguments to a function so that the function call looks like such.

(define (function arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8)
    ;; Return minimum argument
    )

How would you, without using lists or the built-in min function, and using the minimum number of comparisons find the smallest argument? I can't identify a way to do so without using lists or using a large number (in my mind) of comparisons between all of the arguments. Does Scheme have some method other than min or some syntax for efficiently finding the smallest value.

user3277752
  • 569
  • 1
  • 9
  • 17
  • By not using lists are you suggesting that you can't use the functions `car` and `cdr` on the arguments? – Jason Sperske Sep 15 '14 at 22:49
  • There are some really smart Scheme programmers here, so I'm sure this will end up being a naive approach, but I think you are going to have to recursively call the function 8 times changing each argument to `nil` and moving the smaller of each position up until you are on the last argument. No `min` implementation of a list of `n` can possibly be lower than `n` comparisons. – Jason Sperske Sep 15 '14 at 22:57
  • Oops, I should have said `n-1` :) – Jason Sperske Sep 15 '14 at 23:01
  • You might find [Another way of writing a mimum value procedure in Scheme?](http://stackoverflow.com/q/18996302/1281433) useful or interesting, even if it doesn't provide an immediate answer. It asks about the same kind of thing, but for four values instead of eight. – Joshua Taylor Sep 16 '14 at 01:00

2 Answers2

4

You know how the two argument min would be implmented, so why not just implement it locally, and then write the expansion that a list based approach would have. That is:

(define (min x1 x2 x3 x4 x4 x5 x6 x7 x8)
  (define (min2 a b)
    (if (< a b) a b))
  (min2 x1 (min2 x2 (min2 x3 (min2 x4 (min2 x5 (min2 x6 (min2 x7 x8))))))))

That's what any approach is going to boil down to eventually. As malisper correctly points out, you're going to need seven comparisons.

If you wanted to, you could reorder the comparisons and reduce some stack space for nested calls:

(define (min x1 x2 x3 x4 x4 x5 x6 x7 x8)
  (define (min2 a b)
    (if (< a b) a b))
  (min2 (min2 (min2 x1 x2) (min2 x3 x4))
        (min2 (min2 x5 x6) (min2 x7 x8))))

That's still seven comparisons, though. At this point, though you're really just looking at different ways of writing the same code, in which case you should look at Another way of writing a mimum value procedure in Scheme?.

Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
3

Something along these lines should work. Normally I would just loop through the arguments and keep track of the minimum seen so far, but since the arguments are taken separately this is the next best thing.

(define (function arg1 ... arg8)
  (let* ((best2 (if (< arg1 arg2) arg1 arg2))
         (best3 (if (< best2 arg3) best2 arg3))
         ...
         (best7 (if (< best6 arg7) best6 arg7)))
    (if (< best7 arg8)
        best7
        arg8)))

This uses a total of seven comparisons which I'm pretty sure is the optimal.

malisper
  • 1,671
  • 1
  • 12
  • 16