2012-02-24 40 views
2

我決定學習編程閱讀/做SICP。計劃 - 二十一點計劃(SICP)/學習編程

我使用DrRacket和http://www.neilvandyke.org/racket-sicp/

我寫了一個酒杯程序https://github.com/fnava621/scheme_blackjack。有用。

你可以讓這個程序更易讀和簡潔嗎?

我有太多評論嗎?沒有足夠的評論?我如何讓這個程序「更好」?

我也扔下了戰書。你可以制定一個使用「最優」策略的程序,並確定玩家獲勝的可能性(使用n個樣本量)?我會做同樣的事情並比較代碼。

感謝您的閱讀/做, 費爾南多·納瓦

+0

也許你應該嘗試寫一個更難的方案變種。球拍相當不同,更容易。我個人不喜歡'如果'。我可以閱讀和理解整個計劃。 – 2012-02-24 18:14:52

回答

3

幾點建議:使用

  1. 避免如此多的突變,即set!
  2. 避免重新定義內置函數,如length
  3. 爲每個函數添加簽名和目的語句。有關說明,請參閱here
  4. 寫測試!嘗試使用rackunit,記錄here
+0

謝謝!!!!!!!!!!!!! – nava 2012-02-26 21:57:53

2

讓我專注於單一功能show-deck。我看到它在做什麼,但遞歸可以簡化一點。使它更容易閱讀可能會稍微低效,但我們在這裏談論52個卡... :)

內部和外部循環糾纏在原始代碼中。這裏有一個版本,理順了那些紛繁他們:

(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 ...),仍然可以得到容易看到的嵌套循環結構的好處的一種方法是使用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的用法。個人而言,如果我正在使用完整球拍寫作,我只需使用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))) 
+0

謝謝!!!!!!!!!!! – nava 2012-02-26 21:58:02