diff --git a/maths/weird_number.py b/maths/weird_number.py new file mode 100644 index 000000000..2834a9fee --- /dev/null +++ b/maths/weird_number.py @@ -0,0 +1,100 @@ +""" +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.")