Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
146 views
in Technique[技术] by (71.8m points)

How can write a program in scheme to find factors of a list of integer? how can extend it into arbitrarily large input?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

"...how can it extend to arbitrarily large input by passing list as a parameter?"

The process described by the posted *factors procedure is not iterative, i.e., not tail-recursive, and it will grow stack space for large inputs. I take it that OP is interested in finding a tail-recursive version of this code to improve the space efficiency.

You can convert this to an iterative process by adding an accumulator to the helper procedure. This allows results to be stored in the accumulator and passed through recursive calls without the need for any further operations when those calls return, i.e., tail recursion.

(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 '()))

Here are the results of tracing the execution of these procedures:

> (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)

Here factors-trace and factors-iter-trace are slightly modified versions of the factors and factors-iter definitions, allowing for a trace. You can see that the %factors process grows in stack size as the computation progresses, but iter maintains a constant stack size.

As others have already answered, the easiest way to use factors-iter with a list of inputs is to use 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))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...