我决定学习阅读/做SICP。
我正在使用DrRacket和http://www.neilvandyke.org/racket-sicp/
我写了一个二十一点程序https://github.com/fnava621/scheme_blackjack。它有效。
你能让这个程序更易读和简洁吗?
我收到了太多评论吗?评论不够?如何让这个程序“更好”?
我也放下了手套。你能制作一个使用“最佳”策略的程序,并确定玩家赢得经销商的概率(使用n个样本大小)吗?我会做同样的事情并比较代码。
感谢您的阅读/做, 费尔南多·纳瓦
答案 0 :(得分:3)
一些建议:
答案 1 :(得分: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
的使用。
就个人而言,如果我正在编写完整的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)))