solutions.problem21   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 69
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 69
rs 10
c 0
b 0
f 0
wmc 6

1 Function

Rating   Name   Duplication   Size   Complexity  
B solve() 0 19 6
1
"""
2
Project Euler Problem 21: Amicable Numbers
3
==========================================
4
5
.. module:: solutions.problem21
6
   :synopsis: My solution to problem #21.
7
8
The source code for this problem can be
9
`found here <https://bitbucket.org/nekedome/project-euler/src/master/solutions/problem21.py>`_.
10
11
Problem Statement
12
#################
13
14
Let :math:`d(n)` be defined as the sum of proper divisors of :math:`n` (numbers less than :math:`n` which divide evenly
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (119/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
15
into :math:`n`).
16
17
If :math:`d(a) = b` and :math:`d(b) = a`, where :math:`a \\neq b`, then :math:`a` and :math:`b` are an amicable pair and
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (120/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
18
each of :math:`a` and :math:`b` are called amicable numbers.
19
20
For example, the proper divisors of :math:`220` are :math:`1, 2, 4, 5, 10, 11, 20, 22, 44, 55` and :math:`110`;
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (111/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
21
therefore :math:`d(220) = 284`. The proper divisors of :math:`284` are :math:`1, 2, 4, 71` and :math:`142`; so
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (110/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
22
:math:`d(284) = 220`.
23
24
Evaluate the sum of all the amicable numbers under :math:`10000`.
25
26
Solution Discussion
27
###################
28
29
Pre-compute :math:`d(n)` for all :math:`n` in our search space and then iterate over :math:`n` searching for
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (108/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
30
:math:`d(n) = m` and :math:`d(m) = n` where :math:`n \\neq m`. Compute the sum of all such :math:`(n, m)`.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (106/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
31
32
.. note:: the pre-computation of :math:`d(n)` for an increasing :math:`n` can be drastically sped up by using sieving
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (117/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
33
          techniques. An alternative, but inferior, method would be to find the divisors of increasing values of
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (112/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
34
          :math:`n` via factorisation.
35
36
Solution Implementation
37
#######################
38
39
.. literalinclude:: ../../solutions/problem21.py
40
   :language: python
41
   :lines: 44-
42
"""
43
44
from lib.numbertheory.sieve import divisors_sieve
45
46
47
def solve():
48
    """ Compute the answer to Project Euler's problem #21 """
49
50
    # Pre-compute d(n) for all n in [2, 9999]
51
    target = 10000
52
    divisor_counts = divisors_sieve(target - 1, proper=True, aggregate="sum")
53
    d_vals = {n + 1: div_count for n, div_count in enumerate(divisor_counts)}
54
    del d_vals[1]  # divisors_sieve covers the closed interval [1, target - 1], remove d(1)
55
56
    # Identify amicable numbers
57
    amicable_numbers = set()
58
    for n, d_n in d_vals.items():
0 ignored issues
show
Coding Style Naming introduced by
The name n does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
59
        if d_n in d_vals and d_vals[d_n] == n and n != d_n:
60
            amicable_numbers.add(n)
61
            amicable_numbers.add(d_n)
62
63
    # Sum all amicable numbers
64
    answer = sum(amicable_numbers)
65
    return answer
66
67
68
expected_answer = 31626
0 ignored issues
show
Coding Style Naming introduced by
The name expected_answer does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
69