プロジェクト

全般

プロフィール

Problem 21 » 履歴 » バージョン 2

Noppi, 2024/01/04 05:38

1 1 Noppi
[ホーム](https://redmine.noppi.jp) - [[Wiki|Project Euler]]
2
# [[Problem 21]]
3
4
## Amicable Numbers
5
Let $d(n)$ be defined as the sum of proper divisors of $n$ (numbers less than $n$ which divide evenly into $n$).
6
If $d(a) = b$ and $d(b) = a$, where $a \ne b$, then $a$ and $b$ are an amicable pair and each of $a$ and $b$ are called amicable numbers.
7
For example, the proper divisors of $220$ are $1, 2, 4, 5, 10, 11, 20, 22, 44, 55$ and $110$; therefore $d(220) = 284$. The proper divisors of $284$ are $1, 2, 4, 71$ and $142$; so $d(284) = 220$.
8
Evaluate the sum of all the amicable numbers under $10000$.
9
10
## 友愛数
11
d(n) を n の真の約数の和と定義する. (真の約数とは n 以外の約数のことである. )
12
もし, d(a) = b かつ d(b) = a (a ≠ b のとき) を満たすとき, a と b は友愛数(親和数)であるという.
13
14
例えば, 220 の約数は 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110 なので d(220) = 284 である.
15
また, 284 の約数は 1, 2, 4, 71, 142 なので d(284) = 220 である.
16
17
それでは10000未満の友愛数の和を求めよ.
18
19
```scheme
20 2 Noppi
(import (scheme base)
21
        (gauche base)
22
        (math prime)
23
        (scheme list)
24
        (scheme vector))
25
26
(define (non-primes num)
27
  (let ([primes-num (take-while (^n (<= n num)) (primes))]
28
        [iota-4-num (iota (+ num 1 -4) 4)])
29
    (lset-difference = iota-4-num primes-num)))
30
31
(define (proper-divisors num)
32
  (let loop ([n 2] [result '()])
33
    (cond
34
      [(< num (* n n)) (delete-duplicates (cons 1 result))]
35
      [(zero? (mod num n))
36
       (loop (+ n 1) (cons* n (div num n) result))]
37
      [else (loop (+ n 1) result)])))
38
39
(define (sum-divisors lis)
40
  (map
41
    (^n (cons n
42
              (apply + (proper-divisors n))))
43
    lis))
44
45
(define (amicable-numbers num)
46
  (let ([divisors-list (sum-divisors (non-primes num))]
47
        [table (make-vector (+ num 1) #f)])
48
    (for-each
49
      (^[cell]
50
        (let ([a (car cell)]
51
              [b (cdr cell)])
52
          (when (and (not (= a b)) (<= b num))
53
            (set! (vector-ref table a) b))))
54
      divisors-list)
55
    (vector-fold
56
      (^[lis index num-or-f]
57
        (cond
58
          [(not num-or-f) lis]
59
          [(not (vector-ref table num-or-f)) lis]
60
          [(= index (vector-ref table num-or-f))
61
           (set! (vector-ref table index) #f)
62
           (set! (vector-ref table num-or-f) #f)
63
           (cons* index num-or-f lis)]
64
          [else lis]))
65
      '()
66
      (list->vector (iota (+ num 1)))
67
      table)))
68
69
(define answer-21
70
  (apply + (amicable-numbers 9999)))
71
72
(format #t "21: ~d~%" answer-21)
73 1 Noppi
```