我正在浏览Lisp Koans,这很有趣!但我坚持使用计分项目(我有一个糟糕的解决方案)。在这个项目中,我们被要求实现一个名为*Greed*
. 问题描述在这里:
; *Greed* is a dice game where you roll up to five dice to accumulate
; points. The following "score" function will be used to calculate the
; score of a single roll of the dice.
;
; A greed roll is scored as follows:
; * A set of three ones is 1000 points
; * A set of three numbers (other than ones) is worth 100 times the
; number. (e.g. three fives is 500 points).
; * A one (that is not part of a set of three) is worth 100 points.
; * A five (that is not part of a set of three) is worth 50 points.
; * Everything else is worth 0 points.
;
; Examples:
;
; (score '(1 1 1 5 1)) => 1150 points
; (score '(2 3 4 6 2)) => 0 points
; (score '(3 4 5 3 3)) => 350 points
; (score '(1 5 1 2 4)) => 250 points
;
; More scoring examples are given in the tests below:
;
; Your goal is to write the score method.
我的解决方案如下:
警告!如果你还没有玩过这个。不要看到这个!
我使用一个occurs
函数来计算 number 的出现并在 assoc-list 中表示。以及一个为formula-wrapper
函数提供正确参数的formula
函数。formula
计算分数的函数。我的解决方案非常难看!欢迎任何建议!先感谢您。
(defun occurs (lst)
(let ((acc nil))
(dolist (obj lst)
(let ((p (assoc obj acc)))
(if p
(incf (cdr p))
(push (cons obj 1) acc))))
(sort acc #'> :key #'cdr)))
(defun formula-wrapper (lst)
(formula (car lst) (cdr lst)))
(defun formula (number times)
(cond ((= times 0) 0)
((= times 1)
(case number
(1 100)
(5 50)
(otherwise 0)))
((= times 2)
(case number
(1 200)
(5 100)
(otherwise 0)))
((= times 3)
(case number
(1 1000)
(otherwise (* 100 number))))
((= times 4)
(case number
(1 1100)
(5 550)
(otherwise 0)))
((= times 5)
(case number
(1 1200)
(5 600)
(otherwise 0)))
(times 0)))
(defun score (dice)
(let ((rolls (occurs dice)))
(if (null rolls)
0
(apply #'+ (mapcar #'formula-wrapper rolls))))))
测试:
(define-test test-score-of-an-empty-list-is-zero
(assert-equal 0 (score nil)))
(define-test test-score-of-a-single-roll-of-5-is-50
(assert-equal 50 (score '(5))))
(define-test test-score-of-a-single-roll-of-1-is-100
(assert-equal 100 (score '(1))))
(define-test test-score-of-multiple-1s-and-5s-is-the-sum-of-individual-scores
(assert-equal 300 (score '(1 5 5 1))))
(define-test test-score-of-single-2s-3s-4s-and-6s-are-zero
(assert-equal 0 (score '(2 3 4 6))))
(define-test test-score-of-a-triple-1-is-1000
(assert-equal 1000 (score '(1 1 1))))
(define-test test-score-of-other-triples-is-100x
(assert-equal 200 (score '(2 2 2)))
(assert-equal 300 (score '(3 3 3)))
(assert-equal 400 (score '(4 4 4)))
(assert-equal 500 (score '(5 5 5)))
(assert-equal 600 (score '(6 6 6))))
(define-test test-score-of-mixed-is-sum
(assert-equal 250 (score '(2 5 2 2 3)))
(assert-equal 550 (score '(5 5 5 5))))