How to find amicable pairs in scheme? -


i new in scheme. how find "amicable pais"?

(define (sumcd n)   (define s 1 )   (set! m (quotient n 2))   (while (<= m)          (if (=(modulo n i) 0)              (set! s (+ s i)))          (set! (+ 1))    )  ) 

and in main program want check (if (m=sumcd n) , (n=sumcd m)) m , n amicable pair. how can this?

excessive use of set! indicates imperative style of programming, discouraged in scheme. here's racket-specific implementation of sum-of-divisors not use set! @ all.

(define (sum-of-divisors n)   (define-values (q r) (integer-sqrt/remainder n))   (for/fold ((sum (if (and (zero? r) (> q 1)) (add1 q) 1)))             ((i (in-range 2 q))              #:when (zero? (modulo n i)))     (+ sum (quotient n i)))) 

equivalent version in standard r6rs/r7rs scheme, if you're not using racket:

(define (sum-of-divisors n)   (define-values (q r) (exact-integer-sqrt n))   (let loop ((sum (if (and (zero? r) (> q 1)) (+ q 1) 1))              (i 2))     (cond ((>= q) sum)           ((zero? (modulo n i))            (loop (+ sum (quotient n i)) (+ 1)))           (else (loop sum (+ 1)))))) 

note not equivalent set!-based version have. code create inner function, loop, gets tail-called new arguments each time.


now, can define amicable? , perfect? accordingly:

(define (amicable? n)   (define sum (sum-of-divisors n))   (and (not (= n sum))        (= n (sum-of-divisors sum))))  (define (perfect? n)   (= n (sum-of-divisors n))) 

if want test 2 numbers see if amicable pair, can this:

(define (amicable-pair? b)   (and (not (= b))        (= (sum-of-divisors b))        (= b (sum-of-divisors a)))) 

update op's new question how use find amicable pairs between m , n. first, let's define variant of amicable? returns number's amicable "peer":

(define (amicable-peer n)   (define sum (sum-of-divisors n))   (and (not (= n sum))        (= n (sum-of-divisors sum))        sum)) 

if you're using racket, use this:

(define (amicable-pairs-between m n)   (for*/list ((i (in-range m (add1 n)))               (peer (in-value (amicable-peer i)))               #:when (and peer (<= m peer n) (< peer)))     (cons peer))) 

if you're not using racket, use this:

(define (amicable-pairs-between m n)   (let loop ((result '())              (i n))     (if (< m)         result         (let ((peer (amicable-peer i)))           (if (and peer (<= m peer n) (< peer))               (loop (cons (cons peer) result) (- 1))               (loop result (- 1))))))) 

the way works, because lists built right-to-left, i've decided count downward n through m, keeping numbers have amicable peer, , peer within range. (< peer) check ensure amicable pair appears once in results.

example:

> (amicable-pairs-between 0 10000) ((220 . 284) (1184 . 1210) (2620 . 2924) (5020 . 5564) (6232 . 6368)) 

more op updates (wherein asked difference between recursive version , accumulative version is). version of amicable-pairs-between wrote above accumulative. recursive version this:

(define (amicable-pairs-between m n)   (let recur ((i m))     (if (> n)         '()         (let ((peer (amicable-peer i)))           (if (and peer (<= m peer n) (< peer))               (cons (cons peer) (recur (+ 1)))               (recur (+ 1))))))) 

note there no result accumulator time. however, it's not tail-recursive more.


Comments

Popular posts from this blog

how to proxy from https to http with lighttpd -

android - Automated my builds -

python - Flask migration error -