Compare commits
No commits in common. "cfba98d2e0b657758748afc251c9624c16c71e5c" and "d403da53db27a824fc44a328d602c52b37f0d125" have entirely different histories.
cfba98d2e0
...
d403da53db
6 changed files with 71 additions and 32 deletions
0
imp/extern/__init__.py
vendored
0
imp/extern/__init__.py
vendored
|
|
@ -6,7 +6,7 @@ Terminology:
|
||||||
the "prime proper divisors of n".
|
the "prime proper divisors of n".
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from imp.extern.primefac import primefac
|
from imp.math.primefac import primefac
|
||||||
|
|
||||||
def factors(n: int) -> int:
|
def factors(n: int) -> int:
|
||||||
pfactors: list[tuple[int, int]] = []
|
pfactors: list[tuple[int, int]] = []
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
def factorial(n: int) -> int:
|
def factorial(n: int) -> int:
|
||||||
if n == 0: return 1
|
if n == 0: return 1
|
||||||
return n * factorial(n-1)
|
return n * factorial(n-1)
|
||||||
|
|
||||||
|
def
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
from math import gcd, inf
|
from math import gcd
|
||||||
|
from imp.math.numbers import bigomega
|
||||||
from imp.math.numbers import bigomega, factors
|
|
||||||
from imp.extern.primefac import (
|
|
||||||
isprime,
|
|
||||||
primegen as Primes,
|
|
||||||
)
|
|
||||||
|
|
||||||
def coprime(n: int, m: int) -> bool:
|
def coprime(n: int, m: int) -> bool:
|
||||||
return gcd(n, m) == 1
|
return gcd(n, m) == 1
|
||||||
|
|
@ -23,25 +18,68 @@ def semiprime(n: int) -> bool:
|
||||||
'''
|
'''
|
||||||
return almostprime(n, 2)
|
return almostprime(n, 2)
|
||||||
|
|
||||||
def eulertotient(x: int | list) -> int:
|
|
||||||
'''
|
'''
|
||||||
Evaluates Euler's Totient function.
|
Euler's Totient (Phi) Function
|
||||||
Input: `x: int` is prime factorised by Lucas A. Brown's primefac.py
|
|
||||||
else `x: list` is assumed to the prime factorisation of `x: int`
|
|
||||||
'''
|
'''
|
||||||
pfactors = x if isinstance(x, list) else factors(n)
|
def totient(n: int) -> int:
|
||||||
return prod((p-1)*(p**(e-1)) for (p, e) in pfactors)
|
phi = int(n > 1 and n)
|
||||||
# def eulertotient(n: int) -> int:
|
for p in range(2, int(n ** .5) + 1):
|
||||||
# '''
|
if not n % p:
|
||||||
# Uses trial division to compute
|
phi -= phi // p
|
||||||
# Euler's Totient (Phi) Function.
|
while not n % p:
|
||||||
# '''
|
n //= p
|
||||||
# phi = int(n > 1 and n)
|
#if n is > 1 it means it is prime
|
||||||
# for p in range(2, int(n ** .5) + 1):
|
if n > 1: phi -= phi // n
|
||||||
# if not n % p:
|
return phi
|
||||||
# phi -= phi // p
|
|
||||||
# while not n % p:
|
'''
|
||||||
# n //= p
|
Tests the primality of an integer using its totient.
|
||||||
# #if n is > 1 it means it is prime
|
NOTE: If totient(n) has already been calculated
|
||||||
# if n > 1: phi -= phi // n
|
then pass it as the optional phi parameter.
|
||||||
# return phi
|
'''
|
||||||
|
def is_prime(n: int, phi: int = None) -> bool:
|
||||||
|
return n - 1 == (phi if phi is not None else totient(n))
|
||||||
|
|
||||||
|
'''
|
||||||
|
Prime number generator function.
|
||||||
|
Returns the tuple (p, phi(p)) where p is prime
|
||||||
|
and phi is Euler's totient function.
|
||||||
|
'''
|
||||||
|
def prime_gen(yield_phi: bool = False) -> int | tuple[int, int]:
|
||||||
|
n = 1
|
||||||
|
while True:
|
||||||
|
n += 1
|
||||||
|
phi = totient(n)
|
||||||
|
if is_prime(n, phi=phi):
|
||||||
|
if yield_phi:
|
||||||
|
yield (n, phi)
|
||||||
|
else:
|
||||||
|
yield n
|
||||||
|
|
||||||
|
'''
|
||||||
|
Returns the prime factorisation of a number.
|
||||||
|
Returns a list of tuples (p, m) where p is
|
||||||
|
a prime factor and m is its multiplicity.
|
||||||
|
NOTE: uses a trial division algorithm
|
||||||
|
'''
|
||||||
|
def prime_factors(n: int) -> list[tuple[int, int]]:
|
||||||
|
phi = totient(n)
|
||||||
|
if is_prime(n, phi=phi):
|
||||||
|
return [(n, 1)]
|
||||||
|
factors = []
|
||||||
|
for p in prime_gen(yield_phi=False):
|
||||||
|
if p >= n:
|
||||||
|
break
|
||||||
|
# check if divisor
|
||||||
|
multiplicity = 0
|
||||||
|
while n % p == 0:
|
||||||
|
n //= p
|
||||||
|
multiplicity += 1
|
||||||
|
if multiplicity:
|
||||||
|
factors.append((p, multiplicity))
|
||||||
|
if is_prime(n):
|
||||||
|
break
|
||||||
|
if n != 1:
|
||||||
|
factors.append((n, 1))
|
||||||
|
return factors
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
from collections.abc import Iterable
|
|
||||||
from itertools import chain, combinations
|
from itertools import chain, combinations
|
||||||
|
|
||||||
def digits(n: int) -> int:
|
def digits(n: int) -> int:
|
||||||
return len(str(n))
|
return len(str(n))
|
||||||
|
|
||||||
def powerset(iterable: Iterable) -> Iterable:
|
def powerset(iterable):
|
||||||
s = list(iterable)
|
s = list(iterable)
|
||||||
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
|
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue