我编写了以下程序来计算3&的所有倍数的总和。方案中低于1000的5。但是,它给我一个不正确的输出。 任何帮助将不胜感激。
(define (multiples)
(define (calc a sum ctr cir)
(cond (> a 1000) (sum)
(= ctr 7) (calc (+ a (list-ref cir 0)) (+ sum a) 0 (list 3 2 1 3 1 2 3))
(else (calc (+ a (list-ref cir ctr)) (+ sum a) (+ 1 ctr) (list 3 2 1 3 1 2 3)))))
(calc 0 0 0 (list 3 2 1 3 1 2 3)))
答案 0 :(得分:1)
您可以通过使用累加器(sum
参数)和target
参数来测试何时停止求和,将命令式样式解决方案移植到函数Scheme:
(define (multiples)
(define (multiples-iter num sum target)
(if (> num target)
sum
(multiples-iter (+ 1 num)
(if (or (zero? (mod num 3)) (zero? (mod num 5)))
(+ sum num)
sum)
target)))
(multiples-iter 0 0 1000))
答案 1 :(得分:1)
这是我的(特定于球拍)解决方案,它不涉及很多(或者,对于任何)modulo
次调用,并且是完全通用的(因此您不需要构建OP列出的(3 2 1 3 1 2 3)
列表:
(define (sum-of-multiples a b limit)
(define (sum-of-multiple x)
(for/fold ((sum 0))
((i (in-range 0 limit x)))
(+ sum i)))
(- (+ (sum-of-multiple a) (sum-of-multiple b))
(sum-of-multiple (lcm a b))))
试运行:
> (sum-of-multiples 3 5 1000)
233168
答案 2 :(得分:1)
如果您正在使用Racket,那么使用循环结构可以非常紧凑地执行您的要求:
(for/fold ([sum 0])
([i (in-range 1 1000)]
#:when (or (zero? (modulo i 3)) (zero? (modulo i 5))))
(+ sum i))
=> 233168
答案 3 :(得分:1)
一个问题是您的代码缺少围绕cond
子句的一对括号。
在(cond (> a 1000) (sum)
行中,条件仅为>
,而a
和1000
被解释为在>
为真(即它)时要评估的表单,因此将返回1000作为结果。
另外两个问题(由第一个掩盖)是你在达到7时将ctr初始化为0,而它应该被设置为下一个值,即1,并且你在结果中包含1000。 / p>
您的功能的更正版本是
(define (multiples)
(define (calc a sum ctr cir)
(cond ((>= a 1000) sum)
((= ctr 7) (calc (+ a (list-ref cir 0)) (+ sum a) 1 (list 3 2 1 3 1 2 3)))
(else (calc (+ a (list-ref cir ctr)) (+ sum a) (+ 1 ctr) (list 3 2 1 3 1 2 3)))))
(calc 0 0 0 (list 3 2 1 3 1 2 3)))
同样的算法也可以定义为非递归函数,如下所示:
(define (multiples)
(do ((cir (list 3 2 1 3 1 2 3))
(ctr 0 (+ ctr 1))
(a 0 (+ a (list-ref cir (modulo ctr 7))))
(sum 0 (+ sum a)))
((>= a 1000) sum)))
答案 4 :(得分:0)
(require-extension (srfi 1))
(define (sum-mod-3-5 upto)
(define (%sum-mod-3-5 so-far generator-position steps)
(let ((next (car generator-position)))
(if (> (+ steps next) upto)
so-far
(%sum-mod-3-5 (+ so-far steps)
(cdr generator-position)
(+ steps next)))))
(%sum-mod-3-5 0 (circular-list 3 2 1 3 1 2 3) 0)) ; 233168
对于这个特定的任务,如果将计数器递增1,它将平均执行一半的操作,如果要检查的条件也减少一个。
另外,模数(可能是伪装的分割)比求和更贵。
编辑:我不是Scheme的不同方言的模块化系统的专业人士。此处的SRFI-1扩展仅需要更容易创建循环列表。我找不到Common Lisp(#0=(3 2 1 3 1 2 3) . #0#)
的类似物,但也许更有知识的人会纠正这个。
答案 5 :(得分:0)
如果你绝对想要使用“重复模式”方法,你可以这样做。
这在间隔列表中使用递归,而不是依赖于list-ref
和显式索引。
(define (mults limit)
(define steps '(3 2 1 3 1 2 3))
(define (mults-help a sum ls)
(cond ((>= a limit) sum)
((null? ls) (mults-help a sum steps))
(else (mults-help (+ a (car ls))
(+ a sum)
(cdr ls)))))
(mults-help 0 0 steps))