I am learning scheme to get something new from a programming language and this code below is the solution to Project Euler question 21 but the code runs 10x slower than the listed Python code when I use Chibi-Scheme. Can any Scheme craftsman refactor the code into the Scheme idiom for efficiency.
Scheme Code:
(define (sum-of-amicable-pairs n)
(let ((sums (make-vector n)))
(for-each
(lambda (i)
(vector-set! sums i
(reduce + 0
(filter (lambda (j) (= (remainder i j) 0))
(iota (+ 1 (quotient i 2)) 1 1)))))
(iota n 0 1))
(let loop ((res (make-vector n 0))
(i 0))
(cond
((= i n) (reduce + 0 (vector->list res)))
((and (< (vector-ref sums i) n) (not (= (vector-ref sums i) i))
(= (vector-ref sums (vector-ref sums i)) i))
(begin
(vector-set! res i i)
(vector-set! res (vector-ref sums i) (vector-ref sums i))
(loop res (+ 1 i))))
(else
(loop res (+ i 1)))))))
(display (sum-of-amicable-pairs 10000))
(newline)
Python code:
def amicable_pairs(n):
"""returns sum of all amicable pairs under n. See project euler for
definition of an amicable pair"""
div_sum = [None]*n
amicable_pairs_set = set()
for i in range(n):
div_sum[i] = sum([j for j in range(1, i/2 + 1) if i%j == 0])
for j in range(n):
if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:
amicable_pairs_set.add(j)
amicable_pairs_set.add(div_sum[j])
#print sum(amicable_pairs_set)
return sum(list(amicable_pairs_set))