0

配列を移動し、配列の終わりまで最小値を記憶してから、最小値を返したい。しかし、スキームでこれを行う方法に途方に暮れています

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

配列内の最小値を取得したい場合に加えて、配列形式のままで次に小さい値も取得したい場合

これはスキームでどのように行われますか?

4

5 に答える 5

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

ベクトルをリストに変換するコストがかかります。

于 2013-10-17T17:56:39.797 に答える
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 ) の定義を参照してください。

重要なのは、配列だけでなく他のものでも機能するようにし、それを頻繁に行う場合は、それを言語の一部にすることです。

于 2013-10-17T18:08:57.640 に答える
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ベクトルの場合、効率が問題にならない場合は、これらの関数を とともに使用できます。

于 2013-10-17T17:53:20.083 に答える
0

ここにいくつかの標準的な R6RS 実装があります (タイトル広告の質問で Racket ではなく、Scheme を記述したため)。私はそれを機能させるために何をすべきかをコメントしました#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
于 2013-10-17T19:39:48.593 に答える
0

すでに多くの素晴らしい回答がありますが、(直接の翻訳以外に) 最も簡単なのは、ラケットでサポートされている SRFI 43 で提供されている vector-fold に関して vector-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

コードが機能するかどうかわからないのですが、私のスキームの実装は完全な srfi 43 ライブラリを提供していません。

于 2013-10-18T19:05:43.240 に答える