-
Notifications
You must be signed in to change notification settings - Fork 0
/
ex_1_33.clj
52 lines (46 loc) · 1.84 KB
/
ex_1_33.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
(ns sicp.chapter-1.part-3.ex-1-33
(:require
[sicp.misc :as m]))
; Exercise 1.33
;
; You can obtain an even more general version of accumulate (Exercise 1.32)
; by introducing the notion of a filter on the terms to be combined.
;
; That is, combine only those terms derived from values in the range that satisfy a specified condition.
; The resulting filtered-accumulate abstraction takes the same arguments as accumulate,
; together with an additional predicate of one argument that specifies the filter.
; Write filtered-accumulate as a procedure. Show how to express the following using filtered-accumulate:
;
; 1. the sum of the squares of the prime numbers in the interval a to b
; (assuming that you have a prime? predicate already written)
; 2. the product of all the positive integers less than n
; that are relatively prime to n (i.e., all positive integers i<n such that GCD(i,n)=1).
(defn filtered-accumulate
[combiner null-value term a next-fn b filter?]
(if (> a b)
null-value
(if (filter? a)
(combiner (term a)
(filtered-accumulate combiner null-value term (next-fn a) next-fn b filter?))
(combiner null-value
(filtered-accumulate combiner null-value term (next-fn a) next-fn b filter?)))))
(defn filtered-accumulate-iter
[combiner null-value term a next-fn b filter?]
(letfn [(iter
[a result]
(if (> a b)
result
(iter (next-fn a)
(if (filter? a)
(combiner (term a) result)
result))))]
(iter a null-value)))
; 1. ----------
(defn sum-of-primes
[a b]
(filtered-accumulate-iter + 0 m/square a inc b m/prime?))
; 2. ----------
(defn product-of-primes
[number]
(let [self-gcd? (fn [x] (= 1 (m/gcd x number)))]
(filtered-accumulate-iter * 1 identity 1 inc number self-gcd?)))