如何在方案中编写程序来查找整数列表的因子?如何将其扩展为任意大的输入?

问题描述

这是单个整数的代码,如何将list作为参数传给任意大的输入?

(define (factors n)
  (define (*factors d)
    (cond ((> d n) (list))
          ((= (modulo n d) 0) (cons d (*factors (+ d 1))))
          (else (*factors (+ d 1)))))
  (*factors 1))
            
(display (factors 1111111))
(newline)

解决方法

如果您有一个对一个值执行某些操作的过程,您可以使用 map 对列表的所有元素执行此操作。

(map factors '(50 256 1911))
; ==> ((1 2 5 10 25 50)
;      (1 2 4 8 16 32 64 128 256)
;      (1 3 7 13 21 39 49 91 147 273 637 1911))
,

"...如何通过将列表作为参数传递来扩展到任意大的输入?"

发布的 *factors 过程描述的过程不是迭代的,即不是尾递归的,并且它会为大输入增加堆栈空间。我认为 OP 有兴趣找到此代码的尾递归版本以提高空间效率。

您可以通过向辅助过程添加累加器将其转换为迭代过程。这允许将结果存储在累加器中并通过递归调用传递,而无需在这些调用返回时进行任何进一步的操作,即尾递归。

(define (factors-iter n)
  (define (iter d result)
    (cond ((> d n) (reverse result))
          ((zero? (modulo n d))
           (iter (+ d 1) (cons d result)))
          (else
           (iter (+ d 1) result))))
  (iter 1 '()))

以下是跟踪这些过程的执行结果:

> (factors-trace 8)
|(%factors 1 8)
| (%factors 2 8)
| |(%factors 3 8)
| |(%factors 4 8)
| | (%factors 5 8)
| | (%factors 6 8)
| | (%factors 7 8)
| | (%factors 8 8)
| | |(%factors 9 8)
| | |()
| | (8)
| |(4 8)
| (2 4 8)
|(1 2 4 8)
(1 2 4 8)

> (factors-iter-trace 8)
|(iter 1 8 ())
|(iter 2 8 (1))
|(iter 3 8 (2 1))
|(iter 4 8 (2 1))
|(iter 5 8 (4 2 1))
|(iter 6 8 (4 2 1))
|(iter 7 8 (4 2 1))
|(iter 8 8 (4 2 1))
|(iter 9 8 (8 4 2 1))
|(1 2 4 8)
(1 2 4 8)

此处的 factors-tracefactors-iter-tracefactorsfactors-iter 定义的略微修改版本,允许进行跟踪。您可以看到 %factors 进程的堆栈大小随着计算的进行而增长,但 iter 保持恒定的堆栈大小。

正如其他人已经回答的那样,将 factors-iter 与输入列表一起使用的最简单方法是使用 map

> (map factors-iter '(4 42 314 2998))
((1 2 4) (1 2 3 6 7 14 21 42) (1 2 157 314) (1 2 1499 2998))

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...