如何使用高阶函数解决这个球拍问题?

时间:2018-09-21 08:51:32

标签: scheme racket primes higher-order-functions sieve

我被困在第二季度。

  

Q1。编写一个将数字和数字列表拖放可整除的函数,然后返回一个新列表,该列表仅包含那些不能被数字“不可平分”的数字。

这是我对第一季度的回答。

(define (drop-divisible x lst)
    (cond [(empty? lst) empty] 
    ; if the number in the list is equal to the divisor 
    ; or the number is not divisible, add it to the result list 
    [(or (= x (first lst))(< 0 (remainder (first lst) x))) (cons (first lst) (drop-divisible x (rest lst)))] 
    [else (drop-divisible x (rest lst))]))


(module+ test
(check-equal? (drop-divisible 3 (list 2 3 4 5 6 7 8 9 10)) (list 2 3 4 5 7 8 10)))
  

Q2。使用可整除和(一个或多个)高阶函数过滤,映射,折叠,折叠。 (即无显式递归),编写一个函数,该函数将一个除数列表,一个要测试的数字列表以及对除数列表中的每个元素均进行整除。这是您的代码应通过的测试

(module+ test
    (check-equal? (sieve-with '(2 3) (list 2 3 4 5 6 7 8 9 10)) (list 2 3 5 7)))

我可以提出一个仅包含第二个列表的代码段,其功能与解决Q1的功能相同。

(define (sieve-with divisors lst) 
    (filter (lambda (x) ((lambda (d)(or (= d x)(< 0 (remainder x d)))) divisors)) lst))

我尝试使用“地图”修改代码段,但无法使其按预期工作。我也看不到如何在这里使用“文件夹”。

1 个答案:

答案 0 :(得分:3)

在这种情况下,foldl是使用的正确工具(当除数按升序排列时,foldr也会给出正确的答案,尽管效率较低)。这个想法是获取输入列表,并对除数列表中的每个元素重复应用drop-divisible。因为我们在两次调用之间累积了结果,所以最后我们将获得一个列表,该列表由除数的 all 过滤。这就是我的意思:

(define (sieve-with divisors lst)
  ; `e` is the current element from the `divisors` list
  ; `acc` is the accumulated result
  (foldl (lambda (e acc) (drop-divisible e acc))
         lst        ; initially, the accumulated result
                    ; is the whole input list
         divisors)) ; iterate over all divisors

我使用了lambda来明确显示参数名称,但实际上您可以直接传递drop-divisible。我宁愿写这个简短的实现:

(define (sieve-with divisors lst)
  (foldl drop-divisible lst divisors))

无论哪种方式,它都能按预期工作:

(sieve-with '(2 3) '(2 3 4 5 6 7 8 9 10))
=> '(2 3 5 7)