1

はじめまして、

概要

'(+) または '(-) をデータとして cond (評価されない) に渡すのに問題があります。独自に、(+) または (-) を返し、引数として恒等要素 (0) を返します。

ヘルプ!

バックグラウンド。

コード内の非標準スキーム用。

この本では; 文はフラットなリストで、単語は記号と文字列です。トピックを説明するライブラリの一部である simple.scm には、every、keep、accumulate の 3 つの高次関数/手順があります。

  1. (すべての関数データ) [データのすべての要素に対してこの関数を実行]
  2. (predicate? data を保持) [predicate? data を渡す要素を保持? テスト]
  3. (accumulate function data) [すべてのデータを関数の形式に収集 — keep と組み合わせて無効なデータを削除] 例: (accumulate + (keep number? data)) [非数値を削除し、残りの数値を合計し、数値が見つからない場合はゼロ]

データフロー。

演習8.11は gpa 計算手順です。命令では、ラムダまたは再帰は許可されていません (シーケンシャルに読み取られた場合はまだ教えられていません)。

私が試した最初の実装では、1 つのセンテンスで複数の成績を取得し、それぞれのセンテンスを 1 つの成績で出力します。次に、この出力をヘルパー プロシージャに渡します。

単一グレードの出力に + または - が含まれる場合、たとえば '(a+) が '(a) と '(+) に分割され、すべての出力がさらにヘルパー プロシージャに渡されます。

次に、cond がスコアを割り当てます

a 4
b 3
c 2
d 1
e 0
+ 0.33
- -0.33

これは、私の頭の中でしか機能しませんでした (なぜコンピューターは心のように機能しないのですか?) '(a+) や '(a-) のようなグレードが分離されている場合、'(a) は適切に処理されますが、'(+) または'(-) は恒等要素 (0) に評価され、gpa への追加に失敗します。

'(+) と '(-) を式ではなくデータとして渡す方法はありますか? または、(0) を返す前に cond で使用できる任意のデータに変換できますか?

現在のバージョン、各学年の長いコンドは機能しますが、ひどいものです。関数型プログラミングではなく、実装が必須のように感じさせます。

コード。

間違ったgpaを返します(0.33または-0.33を追加しません):また、入力タイプのチェックイン(gpa-helper)が見事に失敗しました。

(define (gpa gradesset)
    (/ (accumulate + (every gpa-helper gradesset)) (count gradesset)) )

(define (gpa-helper gradewrd)
    (cond   ((or (< (count gradewrd) 1) (> (count gradewrd) 2)) '(Please use valid grade input))
            ((= (count gradewrd) 1) (gpa-allocator (keep valid-grade? gradewrd)))
            ((= (count gradewrd) 2) (every gpa-helper (keep valid-grade? gradewrd)))
            (else '(Please check that all grades entered are valid)) ) )

(define (gpa-allocator gradeletter+-)
    (cond   ((equal? gradeletter+- 'a) 4)
            ((equal? gradeletter+- 'b) 3)
            ((equal? gradeletter+- 'c) 2)
            ((equal? gradeletter+- 'd) 1)
            ((equal? gradeletter+- 'e) 0)
            ((equal? gradeletter+- +) .33)
            ((equal? gradeletter+- -) (- .33))
            (else 0) ) )

(define (valid-grade? gradein)
    (if (member? gradein '(+ - a+ a a- b+ b b- c+ c c- d+ d d- e)) #t #f) )

個々のスコアの文を返すやり直しバージョン。'(+) および '(-) によって返される 0 は、ここに表示されます。正常な入力型チェックを実装しますが、新しい問題が発生します。(1 つの結果を累積 + ing)

(define (gpa gradesset)
    (every gpa-cleaner gradesset) )

(define (gpa-cleaner gradewrd)
    (cond   ((or (< (count gradewrd) 1) (> (count gradewrd) 2)) 0)
            (else (every gpa-accumulator gradewrd)) ) )

(define (gpa-accumulator gradewrd)
    (/ (accumulate + (every gpa-helper gradewrd)) (count gradewrd)) )

(define (gpa-helper gradewrd)
    (cond   ((= (count gradewrd) 1) (gpa-allocator (keep valid-grade? gradewrd)))
            ((= (count gradewrd) 2) (every gpa-helper (keep valid-grade? gradewrd)))
            (else '(Please check that all grades entered are valid)) ) )

(define (gpa-allocator gradeletter+-)
    (cond   ((equal? gradeletter+- 'a) 4)
            ((equal? gradeletter+- 'b) 3)
            ((equal? gradeletter+- 'c) 2)
            ((equal? gradeletter+- 'd) 1)
            ((equal? gradeletter+- 'e) 0)
            ((equal? gradeletter+- +) .33)
            ((equal? gradeletter+- -) (- .33))
            (else 0) ) )

(define (valid-grade? gradein)
    (if (member? gradein '(+ - a b c d e)) #t #f) )

Slib 3b3 で SCM バージョン 5e7 を使用し、Simply Scheme で提供される追加のライブラリ (上記の背景の下に提供されているリンク — Simply.scm、functions.scm、ttt.scm、match.scm、database.scm) と、回答を入力するライブラリロードされたすべてのエクササイズに対して。

4

2 に答える 2

2

+orを (プロシージャとしてではなく)シンボル-として渡す必要がある場合は、最初に引用する必要があります。

'+
'-

例えば:

((equal? gradeletter+- '+) .33)
((equal? gradeletter+- '-) -.33)

gpa-allocatorしかし、文脈から、手順が正しいとは思いません。等級はaまたはである可能性があります。条件は、またはが実際の等級であるa+ことを暗示していますが、これは誤りです。+-

おそらく、成績を文字列として表し、string-ref)文字列の最初の文字を使用してそれが であるかどうかを判断し#\a, #\b, #\c, #\d, #\e、(文字列の長さが 1 より大きい場合) 文字列の 2 番目の文字が#\+またはであるかどうか#\-を確認する必要があります。その後、適切な2 つの値を加算することにより、グレードの値. または、グレードをシンボルとして渡し、それを文字列に変換することもできます. これは私が意味するものです:

(define (gpa-allocator gradeletter+-)
  (let ((grade (symbol->string gradeletter+-)))
    (+ (case (string-ref grade 0)
         ((#\a #\A) 4)
         ((#\b #\B) 3)
         ((#\c #\C) 2)
         ((#\d #\D) 1)
         ((#\e #\E) 0)
         (else 0))
       (if (> (string-length grade) 1)
           (case (string-ref grade 1)
             ((#\+) 0.33)
             ((#\-) -0.33)
             (else 0))
           0))))

それをテストすることを忘れないでください:

(gpa-allocator 'A)
=> 4.0
(gpa-allocator 'A+)
=> 4.33
(gpa-allocator 'A-)
=> 3.67
于 2013-04-29T15:03:24.053 に答える
1

Oscar は何が問題なのかについては正しいのですが、彼のソリューションでは単純なスキーム ブックでは使用されていない関数が使用されています。

これが、その本のその章を読んだときの私の解決策です

(define (gpa l-grades);;letter grades
    (/  (accumulate + (every grade-value-mapper l-grades))
        (count l-grades)
 )   )



(define (grade-value-mapper l-grade)
    (let ((grade (first l-grade))
        (g-mod (lambda (x) 
            (cond   ((equal? '+ (bf l-grade))
                    (+ 1/3 x))
                ((equal? '- (bf l-grade))
                    (- 1/3 x))
                (else x)
        ))     )  )
        (cond   ((equal? (first grade) 'a) (g-mod 4))
            ((equal? (first grade) 'b) (g-mod 3))   
            ((equal? (first grade) 'c) (g-mod 2))   
            ((equal? (first grade) 'd) (g-mod 1))   
            (else 0)
 )   )   )  

私の最高の仕事ではありませんが、お役に立てば幸いです。独自の定義に引き出すことができるgmod。あなたはそう呼ぶでしょう ((gmod l-grade) 4)

またはより多くのアブレーションを引き出します

((gmod l-grade) (文字値 (最初の l-grade)))

(let ... (grade ...) ...) が本当にうまくいっているとは思いません。grade-value-mapper に渡されるのは単一の成績です。

入力クリーナー/チェッカーを関数 grade-value-mapper に最初の cond 句として追加できます。

于 2013-05-01T01:04:17.603 に答える