Well, it all depends on your definition of elegant. For me, an elegant solution is one that is short, clear, idiomatic and uses existing procedures (that is, it doesn't reinvent the wheel). Here's my shot:
(require srfi/1) ; import `list-index`
(require srfi/26) ; import `cute`
(define (min-position lst)
(and (not (null? lst))
(list-index (cute = (apply min lst) <>) lst)))
Here's how it works:
(apply min lst)
finds the minimum element in the list, using the built-inmin
procedure(cute = (apply min lst) <>)
usescute
for creating a specialized predicate that will return#t
whenever an element is equal to the minimum, making sure that we find the minimum only once(list-index (cute = (apply min lst) <>) lst)
useslist-index
with the previous predicate to find the index with the first minimum element in the list- The
(and (not (null? lst)) … )
part is there for handling the edge case where the input list is empty
Short and sweet. The only disadvantage is that it traverses the input list twice, once for finding the minimum element and once again for finding the index of that element. But that's a small price to pay, and it's still an O(n)
solution that works as expected:
(min-position '(9 8 7 6 5))
=> 4
(min-position '(9 8 1 6 5))
=> 2
(min-position '(0 1 2))
=> 0
(min-position '())
=> #f