这个函数的要求是找出1个数的因数,求出这些因数当中最大的前n个因数之和。

完整的要求是这样的: 函数要求

思路

求因数的和,自然要有了因数才行。查了一下racket的reference,没有找到因数分解的函数, 这就意味着要动手写一个。

有了因数之后,也许需要排序,也许不需要,即使要排序,racket也有内置的排序函数可用。 然后,只需要取出前a个数再求和即可。取出前x个元素,这个可以直接使用racket内置的take函数, 求和就不必说了,必定是有内置函数的。

至此,这个问题就很明了了,就是要写一个因数分解函数。

函数实现

因数分解基本上就是遍历,挨个尝试每个数能不能整除,在racket里边,这个必然是用递归实现。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(define (find-factors n)
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  (define (_factors i x)
    (cond
      ((or (>= 0 i)(>= 0 x))
       '())
      ((zero? (remainder i x))
       (cons x (_factors i (sub1 x))))
      (else
       (_factors i (sub1 x)))))
  (_factors n n))

递归函数外面再套一层壳,这就齐活儿了。

求和函数就很简单了,直接调用racket内置函数就行了。

1
2
3
(define (sum-factor n a)
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  (apply + (take (find-factors n) a)))

要是觉得写成2个函数太啰嗦了,那就直接合二为一。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(define (sum-factor n a)
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  (define (_factors i x)
    (cond
      ((or (>= 0 i)(>= 0 x))
       '())
      ((zero? (remainder i x))
       (cons x (_factors i (sub1 x))))
      (else
       (_factors i (sub1 x)))))
  (apply + (take (_factors n n) a)))

测试结果

做了2组测试,(sum-factor 24 3) = 44(sum-factor 999 5) = 1507,看上去一切正常。

benchmark一下,

1
2
3
4
(time
 (void
  (map (lambda (x) (sum-factor 999 5))
       (make-list 10000 1))))

Dr Racket v8.10下跑10000次用时0.371s,似乎也不太慢。😂

收工。