"""
https://en.wikipedia.org/wiki/Weird_number
Fun fact: The set of weird numbers has positive asymptotic density.
"""
from math import sqrt
def factors(number: int) -> list[int]:
"""
>>> factors(12)
[1, 2, 3, 4, 6]
>>> factors(1)
[1]
>>> factors(100)
[1, 2, 4, 5, 10, 20, 25, 50]
# >>> factors(-12)
# [1, 2, 3, 4, 6]
"""
values = [1]
for i in range(2, int(sqrt(number)) + 1, 1):
if number % i == 0:
values.append(i)
if int(number // i) != i:
values.append(int(number // i))
return sorted(values)
def abundant(n: int) -> bool:
"""
>>> abundant(0)
True
>>> abundant(1)
False
>>> abundant(12)
True
>>> abundant(13)
False
>>> abundant(20)
True
# >>> abundant(-12)
# True
"""
return sum(factors(n)) > n
def semi_perfect(number: int) -> bool:
"""
>>> semi_perfect(0)
True
>>> semi_perfect(1)
True
>>> semi_perfect(12)
True
>>> semi_perfect(13)
False
# >>> semi_perfect(-12)
# True
"""
values = factors(number)
r = len(values)
subset = [[0 for i in range(number + 1)] for j in range(r + 1)]
for i in range(r + 1):
subset[i][0] = True
for i in range(1, number + 1):
subset[0][i] = False
for i in range(1, r + 1):
for j in range(1, number + 1):
if j < values[i - 1]:
subset[i][j] = subset[i - 1][j]
else:
subset[i][j] = subset[i - 1][j] or subset[i - 1][j - values[i - 1]]
return subset[r][number] != 0
def weird(number: int) -> bool:
"""
>>> weird(0)
False
>>> weird(70)
True
>>> weird(77)
False
"""
return abundant(number) and not semi_perfect(number)
if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)
for number in (69, 70, 71):
print(f"{number} is {'' if weird(number) else 'not '}weird.")