在方案中找到最小数组

时间:2022-08-22 13:04:31

Want to move thru the array and remember the smallest value until end of array and then return the smallest one. But am at a loss on how to do this in scheme

想要通过数组移动并记住最小值,直到数组结束,然后返回最小的数组。但我不知道如何在计划中这样做

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

If i want to get the smallest value in a array and in addition also want the next smallest value whilst keeping it in array form

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

how would this be done in scheme?

如何在计划中完成?

5 个解决方案

#1


0  

Here are some standard R6RS implementations (since you wrote Scheme and not Racket in your title ad question). I've commented what to do to get it to work in #lang racket

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

#!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

#2


1  

You can iterate over a vector/array just like you'd normally do:

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

(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))))))

You could also use a combination of primitive Scheme functions as:

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

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

with the cost being converting a vector to a list.

成本是将矢量转换为列表。

#3


1  

This depends on the implementation.

这取决于实施。

Professionals programmers will try to avoid reinventing the wheel, and use a function like min, which just works.

专业程序员会尽量避免重新发明*,并使用像min这样的功能。

Code like the above can be translated "literally", preserving the meaning of the C code:

像上面这样的代码可以“逐字地”翻译,保留了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)

But this is not great stylistic form to an experienced Racket programmer. Not only does it only work on vectors, but the code is too concerned with indices.

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

Why not just work on the elements of the thing we care about instead? Here's what that looks like when we change the focus of the iteration:

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

#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)

This is a little better.

这样好一点。

If we were to do something like this in multiple places, it might be worthwhile to see if we can clean it up some more. In Racket, it's probably better to write this in such a way that you can avoid thinking about the silly loop details over and over. As a concrete example of how to generalize and clean this up, see the definition of for/max here (or here).

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

The point is, make it work on other things besides just arrays, and if you end up doing it a lot, make it a part of your language.

关键是,除了数组之外,还可以使用其他东西,如果你最终做了很多,那就把它作为你语言的一部分。

#4


0  

Do you have a list or a vector?

你有一个列表或向量吗?

For lists, the min function is part of the scheme R5RS standard.

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

(min 5 1 4 23 4)

or

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

or you could roll your own

或者你可以自己动手

(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))))))))

For a vector, you could still use these functions along with vector->list, if efficiency is not a concern.

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

#5


0  

A lot of great answers already, but I think the most straightforward (besides a direct translation) is to implement a vector-min in terms of the vector-fold provided for in SRFI 43 which is supported by racket.

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

(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

Not sure if the code works, my scheme implementation doesn't provide the full srfi 43 library.

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

#1


0  

Here are some standard R6RS implementations (since you wrote Scheme and not Racket in your title ad question). I've commented what to do to get it to work in #lang racket

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

#!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

#2


1  

You can iterate over a vector/array just like you'd normally do:

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

(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))))))

You could also use a combination of primitive Scheme functions as:

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

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

with the cost being converting a vector to a list.

成本是将矢量转换为列表。

#3


1  

This depends on the implementation.

这取决于实施。

Professionals programmers will try to avoid reinventing the wheel, and use a function like min, which just works.

专业程序员会尽量避免重新发明*,并使用像min这样的功能。

Code like the above can be translated "literally", preserving the meaning of the C code:

像上面这样的代码可以“逐字地”翻译,保留了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)

But this is not great stylistic form to an experienced Racket programmer. Not only does it only work on vectors, but the code is too concerned with indices.

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

Why not just work on the elements of the thing we care about instead? Here's what that looks like when we change the focus of the iteration:

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

#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)

This is a little better.

这样好一点。

If we were to do something like this in multiple places, it might be worthwhile to see if we can clean it up some more. In Racket, it's probably better to write this in such a way that you can avoid thinking about the silly loop details over and over. As a concrete example of how to generalize and clean this up, see the definition of for/max here (or here).

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

The point is, make it work on other things besides just arrays, and if you end up doing it a lot, make it a part of your language.

关键是,除了数组之外,还可以使用其他东西,如果你最终做了很多,那就把它作为你语言的一部分。

#4


0  

Do you have a list or a vector?

你有一个列表或向量吗?

For lists, the min function is part of the scheme R5RS standard.

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

(min 5 1 4 23 4)

or

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

or you could roll your own

或者你可以自己动手

(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))))))))

For a vector, you could still use these functions along with vector->list, if efficiency is not a concern.

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

#5


0  

A lot of great answers already, but I think the most straightforward (besides a direct translation) is to implement a vector-min in terms of the vector-fold provided for in SRFI 43 which is supported by racket.

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

(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

Not sure if the code works, my scheme implementation doesn't provide the full srfi 43 library.

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