def maximum_totient_ratio_prime(max_n): """Return number n < max_n with maximum n/totient(n) ratio. Euler's product formula: n = (p1**k1) * (p2**k2) * ... totient(n) = n * (1 - 1/p1) * (1 - 1/p2) * ... = n * (p1 - 1)/p1 * (p2 -1)/p2 * ... n/totient(n) = (p1*p2*...)/((p1-1)*(p2-1)*...) -> increases as more prime are added. where p1, p2, ... are primes. Per analysis, the n with maximum n/totient(n) for any given range will be the product of primes since that number has the maximum count of distinct primes p1, p2, ... :param max_n: maximum n to check :return: n with the maximum n/totient(n) ratio in the form: (n, totient(n), n/totient(n)) """ prime_list = common.prime_list_mr(0, 1000) n = 1 ratio = 1.0 for prime in prime_list: n *= prime ratio *= prime/(prime-1) if n > max_n: n = n // prime ratio *= (prime-1)/prime break f = int(0.5 + n/ratio) max_ratio = (n, f, ratio) return max_ratio
def minimum_totient_ratio_permuation(max_n): """Return number n < max_n with minimum n/totient(n) ratio where n and totient(n) are permutations of each other. Euler's product formula: n = (p1**k1) * (p2**k2) * ... totient(n) = n * (1 - 1/p1) * (1 - 1/p2) * ... = n * (p1 - 1)/p1 * (p2 -1)/p2 * ... n/totient(n) = (p1*p2*...)/((p1-1)*(p2-1)*...) -> increases as more prime are added. where p1, p2, ... are primes. :param max_n: maximum n to check :return: n with the minimum n/totient(n) ratio in the form: (n, totient(n), n/totient(n)) """ prime_list = common.prime_list_mr(2, (max_n+1)//2) # Find index of prime closest to sqrt(max_n) sqrt_max_n = math.sqrt(max_n) a = int(sqrt_max_n) while True: if a in prime_list: break else: a -= 1 index_mid = prime_list.index(a) min_ratio = (0, 0, 0, 0, 10.0) # a loops down from sqrt(max_n), b loops up from sqrt(max_n) for index_a in reversed(range(index_mid//2, index_mid)): for index_b in range(index_mid, len(prime_list)): a = prime_list[index_a] b = prime_list[index_b] prod = a * b if prod > max_n: break else: ratio = a*b/((a-1)*(b-1)) f = int(0.5 + prod/ratio) if common.is_permutation(str(prod), str(f)): # print(a, b, prod, f, ratio) if ratio < min_ratio[-1]: min_ratio = (a, b, prod, f, ratio) break return min_ratio
def test_common(): # variables ordered_list = list(range(-10, 10)) prime_list_10 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] # power_digit_sum common.power_digit_sum(2, 15) == 26 # index_in_ordered_list assert common.index_in_ordered_list(-10, ordered_list) == ordered_list.index(-10) assert common.index_in_ordered_list( -1, ordered_list) == ordered_list.index(-1) assert common.index_in_ordered_list( 0, ordered_list) == ordered_list.index(0) assert common.index_in_ordered_list( 9, ordered_list) == ordered_list.index(9) assert common.index_in_ordered_list( 10, ordered_list) == -1 assert common.index_in_ordered_list(-11, ordered_list) == -1 # is_in_ordered_list assert common.is_in_ordered_list(-10, ordered_list) assert common.is_in_ordered_list( -1, ordered_list) assert common.is_in_ordered_list( 0, ordered_list) assert common.is_in_ordered_list( 9, ordered_list) assert common.is_in_ordered_list( 10, ordered_list) is False assert common.is_in_ordered_list(-11, ordered_list) is False assert common.str_permutation(11, '0123') == '1320' assert common.str_permutation(999999, '0123456789') == '2783915460' # get_factors assert common.get_factors(1) == [1] assert common.get_factors(16) == [1, 2, 4, 8, 16] # sieve_erathosthenes assert common.sieve_erathosthenes(30) == prime_list_10 assert common.sieve_erathosthenes(30) != ordered_list assert common.sieve_erathosthenes2(30) == prime_list_10 assert common.prime_list_mr(0, 30) == prime_list_10 # get_prime_factors assert common.get_prime_factors(0, prime_list_10) == [] assert common.get_prime_factors(2, prime_list_10) == [2] assert common.get_prime_factors(512, prime_list_10) == [2] assert common.get_prime_factors(60, prime_list_10) == [2, 3, 5] assert common.get_prime_factors(6469693230, prime_list_10) == prime_list_10