Skip to content

Commit f37d415

Browse files
Add new algorithm for Armstrong numbers (#4474)
* Add a new algorithm for Armstrong numbers * FAILING = (-153, -1, 0, 1.2, 200, "A", [], {}, None) Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent 40e357f commit f37d415

File tree

1 file changed

+50
-20
lines changed

1 file changed

+50
-20
lines changed

maths/armstrong_numbers.py

+50-20
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
"""
2-
An Armstrong number is equal to the sum of its own digits each raised
3-
to the power of the number of digits.
2+
An Armstrong number is equal to the sum of its own digits each raised to the
3+
power of the number of digits.
4+
45
For example, 370 is an Armstrong number because 3*3*3 + 7*7*7 + 0*0*0 = 370.
5-
An Armstrong number is often called Narcissistic number.
6+
7+
Armstrong numbers are also called Narcissistic numbers and Pluperfect numbers.
8+
9+
On-Line Encyclopedia of Integer Sequences entry: https://oeis.org/A005188
610
"""
11+
PASSING = (1, 153, 370, 371, 1634, 24678051, 115132219018763992565095597973971522401)
12+
FAILING = (-153, -1, 0, 1.2, 200, "A", [], {}, None)
713

814

915
def armstrong_number(n: int) -> bool:
1016
"""
1117
Return True if n is an Armstrong number or False if it is not.
1218
13-
>>> armstrong_number(153)
19+
>>> all(armstrong_number(n) for n in PASSING)
1420
True
15-
>>> armstrong_number(200)
16-
False
17-
>>> armstrong_number(1634)
18-
True
19-
>>> armstrong_number(0)
20-
False
21-
>>> armstrong_number(-1)
22-
False
23-
>>> armstrong_number(1.2)
21+
>>> any(armstrong_number(n) for n in FAILING)
2422
False
2523
"""
2624
if not isinstance(n, int) or n < 1:
@@ -43,15 +41,46 @@ def armstrong_number(n: int) -> bool:
4341
return n == sum
4442

4543

46-
def narcissistic_number(n: int) -> bool:
47-
"""Return True if n is a narcissistic number or False if it is not"""
44+
def pluperfect_number(n: int) -> bool:
45+
"""Return True if n is a pluperfect number or False if it is not
46+
47+
>>> all(armstrong_number(n) for n in PASSING)
48+
True
49+
>>> any(armstrong_number(n) for n in FAILING)
50+
False
51+
"""
52+
if not isinstance(n, int) or n < 1:
53+
return False
54+
55+
# Init a "histogram" of the digits
56+
digit_histogram = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
57+
digit_total = 0
58+
sum = 0
59+
temp = n
60+
while temp > 0:
61+
temp, rem = divmod(temp, 10)
62+
digit_histogram[rem] += 1
63+
digit_total += 1
64+
65+
for (cnt, i) in zip(digit_histogram, range(len(digit_histogram))):
66+
sum += cnt * i ** digit_total
67+
68+
return n == sum
4869

49-
expo = len(str(n)) # power, all number will be raised to
50-
# each digit will be multiplied expo times
51-
temp = [(int(i) ** expo) for i in str(n)]
5270

53-
# check if sum of cube of each digit is equal to number
54-
return n == sum(temp)
71+
def narcissistic_number(n: int) -> bool:
72+
"""Return True if n is a narcissistic number or False if it is not.
73+
74+
>>> all(armstrong_number(n) for n in PASSING)
75+
True
76+
>>> any(armstrong_number(n) for n in FAILING)
77+
False
78+
"""
79+
if not isinstance(n, int) or n < 1:
80+
return False
81+
expo = len(str(n)) # the power that all digits will be raised to
82+
# check if sum of each digit multiplied expo times is equal to number
83+
return n == sum(int(i) ** expo for i in str(n))
5584

5685

5786
def main():
@@ -61,6 +90,7 @@ def main():
6190
num = int(input("Enter an integer to see if it is an Armstrong number: ").strip())
6291
print(f"{num} is {'' if armstrong_number(num) else 'not '}an Armstrong number.")
6392
print(f"{num} is {'' if narcissistic_number(num) else 'not '}an Armstrong number.")
93+
print(f"{num} is {'' if pluperfect_number(num) else 'not '}an Armstrong number.")
6494

6595

6696
if __name__ == "__main__":

0 commit comments

Comments
 (0)