2

私は、SICP の読み取り/実行をプログラムすることを学ぶことにしました。

DrRacket と http://www.neilvandyke.org/racket-sicp/を使用しています。

ブラックジャック プログラムhttps://github.com/fnava621/scheme_blackjackを作成しました。できます。

このプログラムをもっと読みやすく簡潔にすることはできますか?

コメント入れすぎた?コメントが足りない?このプログラムを「より良く」するにはどうすればよいですか?

私もガントレットを投げています。「最適な」戦略を使用し、プレーヤーがディーラーに勝つ確率を決定するプログラムを作成できますか (n サンプル サイズを使用)。同じことをしてコードを比較します。

読んでくれてありがとう、フェルナンド・ナバ

4

2 に答える 2

3

いくつかの提案:

  1. あまり多くの突然変異を使用することは避けてくださいset!
  2. のような組み込み関数を再定義することは避けてくださいlength
  3. 各関数に署名と目的ステートメントを追加します。説明については、こちらをご覧ください。
  4. テストを書いてください!ここrackunitに記載されているを使用してみてください
于 2012-02-24T20:01:23.473 に答える
2

1 つの関数に注目してみましょうshow-deck。何をしているのかはわかりますが、再帰は少し単純化できます。読みやすくすることは少し効率が悪いかもしれませんが、ここでは 52 枚のカードについて話しています... :)

元のコードでは内側と外側のループが絡み合っています。それらを解きほぐす1つのバージョンを次に示します。

(define (show-deck1 first-list second-list)
  (define (outer-loop first-list second-list)
    (cond
      ((null? first-list)
       '())
      (else
       (append (inner-loop (car first-list) second-list)
               (outer-loop (cdr first-list) second-list)))))

  (define (inner-loop x second-list)
    (cond
      ((null? second-list)
       '())
      (else
       (cons (cons x (car second-list))
             (inner-loop x (cdr second-list))))))

  (outer-loop first-list second-list))

簡略化を適用できます。定義をこのように表現すると、 をmap使用してinner-loop.

(define (show-deck2 first-list second-list)
  (cond
    ((null? first-list)
     '())
    (else
     (define x (car first-list))
     (append (map (lambda (y) (cons x y)) second-list)
             (show-deck2 (cdr first-list) second-list)))))

これにより、外側の反復の構造が見やすくなります。さらに一歩map進んで、内側と外側の両方のループに使用(apply append ...)し、 のネストされた使用によって導入されたサブ構造を平坦化するために使用できますmap

(define (show-deck3 first-list second-list)
  (apply append 
         (map (lambda (x)
                (map (lambda (y) (cons x y)) second-list))
              first-list)))

(apply append ...)あなたのバージョンでは、計算を巧みにスレッド化することでこの問題を完全に回避していますが、読みやすさが犠牲になっています。を回避し(apply append ...)、ネストされたループ構造を簡単に確認できる利点を得る1 つの方法は、foldrアプローチではなくアプローチを使用することmapです。

(define (foldr f acc l)
  (cond
    ((null? l) acc)
    (else 
     (f (car l)
        (foldr f acc (cdr l))))))

(define (show-deck first-list second-list) 
  (foldr (lambda (x acc)
           (foldr (lambda (y acc)
                    (cons (cons x y) acc))
                  acc
                  second-list))
         '()
         first-list))

これは、元のコードが以前に行ったものと一致する必要があります。ただし、ループ性を に委譲するfoldrため、これらの関数はすべて のiter使用に消えますfoldr

個人的には、完全な Racket で書いている場合は、forループでコーディングするだけです。:) 次のようになります。

;; If we're allowed to use full Racket:
(define (show-deck first-list second-list)
  (for*/list ([x first-list]
              [y second-list])
    (cons x y)))
于 2012-02-26T06:33:23.217 に答える