def search(goal): """ >>> search(6) 13 >>> search(7) 56003 """ already_searched = set() for prime in primes(): if prime in already_searched: continue positions_list = list(position_combinations(prime)) for positions in positions_list: digits = list(digits_of(prime)) family = set() for digit in range(10): if 0 in positions and digit == 0: continue for pos in positions: digits[pos] = digit number = from_digits(digits) if is_prime(number): already_searched.add(number) family.add(number) if len(family) >= goal: return min(family)
def cancel_unorthodox(numerator, denominator): """ >>> cancel_unorthodox(49, 98) (4, 8) >>> cancel_unorthodox(499, 998) (4, 8) >>> cancel_unorthodox(11, 12) (1, 2) """ n_digits = digits_of(numerator) d_digits = digits_of(denominator) matching_digits = [d for d in n_digits if d in d_digits] for m in matching_digits: if m in n_digits and m in d_digits: n_digits.remove(m) d_digits.remove(m) return from_digits(n_digits), from_digits(d_digits)
def is_palindromic(n): """ >>> is_palindromic(121) True >>> is_palindromic(7337) True >>> any(is_palindromic(n) for n in [47, 349, 1292, 4213]) False """ digits = digits_of(n) return digits == list(reversed(digits))
def gen_numbers(): factorials = dict((n, factorial(n)) for n in range(10)) import itertools for num_digits in itertools.count(1): limit = num_digits * factorials[9] if limit < 10**num_digits: break #for n in range(10, limit + 1): for n in range(10, 50000): #HACK, there aren't any above 50000 if n == sum(factorials[d] for d in digits_of(n)): yield n
def iter_counting_digits(): """ >>> from utility import nth >>> nth(12 - 1, iter_counting_digits()) 1 >>> ''.join(str(d) for d in itertools.islice(iter_counting_digits(), 33)) '123456789101112131415161718192021' """ for i in itertools.count(1): for d in digits_of(i): yield d
def position_combinations(n): """ >>> list(position_combinations(2)) [] >>> list(position_combinations(29)) [(0,)] >>> list(position_combinations(293)) [(0,), (1,), (0, 1)] """ length = len(digits_of(n)) return filter(None, powerset(range(length - 1)))
def reverse_and_add(n): """ >>> reverse_and_add(47) 121 >>> reverse_and_add(349) 1292 >>> reverse_and_add(1292) 4213 >>> reverse_and_add(4213) 7337 """ rev_n = from_digits(list(reversed(digits_of(n)))) return n + rev_n
def cube_permutations(size): """ >>> sorted(cube_permutations(3)) [345, 384, 405] """ cubes_by_digits = defaultdict(list) for i in itertools.count(1): cube = i**3 digits = tuple(sorted(digits_of(cube))) cubes = cubes_by_digits[digits] cubes.append(i) if len(cubes) >= size: return set(cubes)
def truncatable_primes(): seen_primes = set() one_digit_primes = (2, 3, 5, 7) for p in primes(): seen_primes.add(p) digits = digits_of(p) # One-digit primes are not considered truncatable. if len(digits) == 1: continue # All digits besides the first must be odd. if not all(d % 2 == 1 for d in digits[1:]): continue # First and last digit must be prime. if digits[0] not in one_digit_primes or \ digits[-1] not in one_digit_primes: continue # Test whether each truncation is a prime. truncs = sorted(list(from_digits(d) for d in truncations(digits))) if all(t in seen_primes for t in truncs): yield p
def sf(n): """ >>> sf(342) 5 """ return sum(digits_of(f(n)))
from utility import digits_of, isqrt # The maximum value of a is 99, because 99 * 100 = 9900, is the largest # almost-square product with 9 or fewer digits. # Since order doesn't matter for products, we define b to be greater than a. # The maximum value for b is 9999, because 1 * 9999 = 9999 is the product with # the largest value of b having 9 or fewer digits. all_digits = list(range(1, 9 + 1)) solutions = [] for a in range(1, 100): for b in range(a + 1, 10000): c = a * b digits = digits_of(a) + digits_of(b) + digits_of(c) if len(digits) < 9: continue if len(digits) > 9: break assert len(digits) == 9 if sorted(digits) == all_digits: solutions.append(c) print(sum(set(solutions)))
from utility import digits_of print(max(sum(digits_of(a**b)) for a in range(1, 100) for b in range(1, 100)))
import itertools from utility import digits_of, from_digits target_digits = set(range(1, 10)) solutions = [] for limit in [2, 3, 4, 5]: for i in itertools.count(1): digits = [] for m in range(1, limit + 1): digits.extend(digits_of(m * i)) if 0 in digits: continue if len(digits) < 9: continue if len(digits) > 9: break if set(digits) == target_digits: solutions.append(from_digits(digits)) print(max(solutions))
from fractions import Fraction import itertools from utility import digits_of def sqrt_two_frac_terms(): frac = Fraction(0, 1) while True: frac = 1 / (2 + frac) yield 1 + frac count = 0 for term in itertools.islice(sqrt_two_frac_terms(), 1000): if len(digits_of(term.numerator)) > len(digits_of(term.denominator)): count += 1 print(count)
import itertools from utility import digits_of limit = 6 for n in itertools.count(1): digits_n = sorted(digits_of(n)) if all(sorted(digits_of(n * m)) == digits_n for m in range(2, limit + 1)): break print(n)
>>> cancel_unorthodox(499, 998) (4, 8) >>> cancel_unorthodox(11, 12) (1, 2) """ n_digits = digits_of(numerator) d_digits = digits_of(denominator) matching_digits = [d for d in n_digits if d in d_digits] for m in matching_digits: if m in n_digits and m in d_digits: n_digits.remove(m) d_digits.remove(m) return from_digits(n_digits), from_digits(d_digits) two_digit_nums = [i for i in range(10, 100) if 0 not in digits_of(i)] unorthodox_numbers = [] for n in two_digit_nums: for d in two_digit_nums: f = Fraction(n, d) if f >= 1: continue n2, d2 = cancel_unorthodox(n, d) if d2 == 0: continue if (n, d) == (n2, d2): continue f2 = Fraction(n2, d2) if f == f2: unorthodox_numbers.append(f2)
def digit_permutations(n): for digits in itertools.permutations(digits_of(n)): yield from_digits(digits)
def f(n): """ >>> f(342) 32 """ return sum(factorial(d) for d in digits_of(n))
def sg(i): """ >>> sg(5) 7 """ return sum(digits_of(g(i)))
break if __name__ == '__main__': # Generate all four digit primes. four_digit_primes = [] for p in primes(): if p < 1000: continue four_digit_primes.append(p) if p >= 10000: break # Group primes by similar digits. primes_by_digits = defaultdict(list) for p in four_digit_primes: primes_by_digits[frozenset(digits_of(p))].append(p) # Strip out digit groups with less than three primes. for digits, primes in list(primes_by_digits.items()): if len(primes) < 3: del primes_by_digits[digits] # Look for arithmetic sequences of length 3. solutions = [] for primes in primes_by_digits.values(): for sequence in find_arithmetic_sequences(primes, 3): digits = [] for n in sequence: digits.extend(digits_of(n)) solutions.append(from_digits(digits))
def is_connection(a, b): """ >>> is_connection(1234, 3456) True """ return (digits_of(a)[-2:] == digits_of(b)[:2])
from utility import primes, digits_of, up_to # In order to maximize the totient, we need to look for "sharp" numbers, having # few prime factors, with those factors being large. limit = 10**7 solutions = [] seen_primes = [] for a in up_to(limit // 2, primes()): for b in seen_primes: n = a * b if n > limit: break t = n t -= t // a if a != b: t -= t // b if sorted(digits_of(n)) == sorted(digits_of(t)): solutions.append((n, n / t)) seen_primes.append(a) solutions.sort(key=lambda x: x[1]) print(min(solutions, key=lambda x: x[1])[0])