在方案中找到最小数组

时间:2013-10-17 17:49:00

标签: arrays scheme racket

想要通过数组移动并记住最小值,直到数组结束,然后返回最小的数组。但我对在方案中如何做到这一点感到茫然

int smallest = INT_MAX;
for (int i = 0; i < array_length; i++) {
if (array[i] < smallest) {
    smallest = array[i];
  }
}

如果我想获得数组中的最小值,另外还想要保持数组形式的下一个最小值

如何在计划中完成?

5 个答案:

答案 0 :(得分:1)

您可以像通常那样迭代矢量/数组:

(define (vector-min v)
  (assert (positive? (vector-length v)))
  (let looping ((i 1) (v-min (vector-ref v 0)))
    (if (= i (vector-length v))
        v-min
        (looping (+ i 1)
                 (min v-min (vector-ref v i))))))

您还可以使用原始Scheme函数的组合:

(define (vector-min v)
  (apply min (vector->list v)))

将成本转换为列表。

答案 1 :(得分:1)

这取决于实施。

专业程序员会尽量避免重新发明轮子,并使用像min这样的功能,这样才能正常工作。

如上所述的代码可以“字面上”翻译,保留C代码的含义:

#lang racket
(define smallest +inf.0)
(define an-array (vector 3 1 4 1 5 9 2 6))
(define array-length 8)
(for ([i (in-range 0 array-length)])
  (when (< (vector-ref an-array i)
           smallest)
    (set! smallest (vector-ref an-array i))))
(print smallest)

但对于经验丰富的球拍程序员来说,这不是一个很好的风格形式。它不仅适用于向量,而且代码过于关注索引。

为什么不只是处理我们关心的事物的元素呢?这是我们改变迭代焦点时的样子:

#lang racket
(define smallest +inf.0)
(define an-array (vector 3 1 4 1 5 9 2 6))
(for ([elt an-array])
  (when (< elt smallest)
    (set! smallest elt)))
(print smallest)

这好一点。

如果我们要在多个地方做这样的事情,那么看看我们是否可以再清理它可能是值得的。在Racket中,最好以这样的方式编写它,以便您可以避免一遍又一遍地考虑愚蠢的循环细节。作为如何概括和清理此问题的具体示例,请参阅for/max here(或here)的定义。

重点是,除了数组之外,还要让它工作在其他东西上,如果你最终做了很多,那就把它作为你语言的一部分。

答案 2 :(得分:0)

你有一个清单或载体吗?

对于列表,min函数是方案R5RS标准的一部分。

(min 5 1 4 23 4)

(apply min '(5 1 3 4 55))

或者你可以自己动手

(define my-min
  (lambda lst
    (let loop ((min (car lst))
               (lst (cdr lst)))
      (if (null? lst)
        min
        (let ((x (car lst)))
          (if (< x min)
            (loop x (cdr lst))
            (loop min (cdr lst))))))))

对于向量,如果效率不是问题,您仍然可以将这些函数与vector->list一起使用。

答案 3 :(得分:0)

以下是一些标准的R6RS实现(因为您在标题广告问题中编写了Scheme而非Racket)。我已经评论了如何让它在#lang racket

中运行
#!r6rs
(import (rnrs base)
        (rnrs lists)
        (rnrs sorting))

;; using vector-sort. Not working in #lang racket
(define (my-min1 vec)
  (if (zero? (vector-length vec))
      +inf.0
      (vector-ref (vector-sort < vec) 0))) 


;; All the rest work on lists. 
;; You may make a wrapper like this (using my-min2 as example)
(define (my-min2-vec vec)
  (my-min2 (vector->list vec)))

;; using min, accepting inexact
(define (my-min2 lst)
   (apply min +inf.0 lst))

;; using base with integers
(define (my-min3 lst)
  (if (null? lst)
      +inf.0
      (apply min lst)))

;; using list-sort. 
;; #lang racket: use sort in place of list-sort and swap arguments.
(define (my-min4 lst)
  (if (null? lst)
      +inf.0
      (car (list-sort < lst))))

;; higher order functions
;; #lang racket: use foldl in place of fold-left 
(define (my-min5 lst)
  (define (min2 x y) 
    (if (< x y) x y))
  (fold-left min2 +inf.0 lst)) 

;; using < and iterating through helper
(define (my-min6 lst)
  (define (my-min6-aux lst min)
    (if (null? lst)
        min
        (my-min6-aux (cdr lst)
                     (let ((cur (car lst)))
                       (if (< cur min) cur min)))))
  (my-min6-aux lst +inf.0))

;; using < and iterating though named let
(define (my-min7 lst)
  (let my-min7-aux ((lst lst)
                    (min +inf.0))
    (if (null? lst)
        min
        (my-min7-aux (cdr lst)
                     (let ((cur (car lst)))
                       (if (< cur min) cur min))))))

(my-min1 '#(3 7 9 1 5))     ; ==> 1
(my-min2-vec '#(3 7 9 1 5)) ; ==> 1.0
(my-min2 '(3 7 9 1 5))      ; ==> 1.0
(my-min3 '(3 7 9 1 5))      ; ==> 1
(my-min4 '(3 7 9 1 5))      ; ==> 1
(my-min5 '(3 7 9 1 5))      ; ==> 1
(my-min6 '(3 7 9 1 5))      ; ==> 1
(my-min7 '(3 7 9 1 5))      ; ==> 1

答案 4 :(得分:0)

已经有很多很棒的答案,但我认为最直接的(除了直接翻译)是根据SRFI 43中提供的向量折叠实现向量分数,这是由球拍支持的。

(define (vector-min vec)
 (vector-fold
    (lambda (n v-min next)
      (if (< v-min next) v-min next))
    (vector-ref vec 0)
    vec))

http://srfi.schemers.org/srfi-43/srfi-43.html#vector-fold

不确定代码是否有效,我的方案实现不提供完整的srfi 43库。