From f4b1fbcafb326d76b4507a2b564c0acc955f88bc Mon Sep 17 00:00:00 2001 From: Tibor Bizjak Date: Sun, 26 Mar 2023 17:35:02 +0200 Subject: [PATCH] Added solutions for N=110-120 --- 110_diophantine_reciprocals_II.py | 54 +++++++++++++++++++++++++++++++ 111_primes_with_runs.py | 46 ++++++++++++++++++++++++++ 112_bouncy_numbers.py | 18 +++++++++++ 113_non-bouncy_numbers.py | 17 ++++++++++ 114_counting_block_I.py | 30 +++++++++++++++++ 115_counting_block_II.py | 35 ++++++++++++++++++++ 116_red_green_blue_tiles.py | 18 +++++++++++ 117_red_green_blue_tilesII.py | 15 +++++++++ 118_pandigital_prime_sets.py | 46 ++++++++++++++++++++++++++ 119_digit_power_sum.py | 34 +++++++++++++++++++ 10 files changed, 313 insertions(+) create mode 100644 110_diophantine_reciprocals_II.py create mode 100644 111_primes_with_runs.py create mode 100644 112_bouncy_numbers.py create mode 100644 113_non-bouncy_numbers.py create mode 100644 114_counting_block_I.py create mode 100644 115_counting_block_II.py create mode 100644 116_red_green_blue_tiles.py create mode 100644 117_red_green_blue_tilesII.py create mode 100644 118_pandigital_prime_sets.py create mode 100644 119_digit_power_sum.py diff --git a/110_diophantine_reciprocals_II.py b/110_diophantine_reciprocals_II.py new file mode 100644 index 0000000..92a826a --- /dev/null +++ b/110_diophantine_reciprocals_II.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +from lib import primegen +from math import log +from operator import mul +from functools import reduce + +def calc(pows): + return (reduce(mul, (2*p + 1 for p in pows)) + 1) // 2 + +def increment(i, pows): + n = 0 + if i < len(pows): + n = pows[i] + return [n + 1] * (i+1) + pows[i+1:] + +def val(pows): + return sum(p*v for p, v in zip(pows, vals)) + +def fpwof2(pows, n): + if len(pows) == 1: + return n-1 + r = (2*n - 1) // reduce(mul, (2*p + 1 for p in pows[1:])) + r = (r - 1) // 2 + while calc([r] + pows[1:]) < n: + r += 1 + return r + +N = 4 * 10**6 + +primes = list(primegen(100)) +vals = [log(p) / log(2) for p in primes] + +i = 0 +pows = [0] +best = fpwof2(pows, N) +best_pows = None + +while not (val(pows) >= best and sum(pows) == len(pows)): + if not i: + pows[0] = fpwof2(pows, N) + if len(pows) > 1 and pows[0] < pows[1]: + pows[0] = pows[1] + if val(pows) < best: + best = val(pows) + best_pows = pows + i = 1 + pows = increment(i, pows) + if val(pows) >= best: + i += 1 + else: + i = 0 + +print(reduce(mul, (n**pw for n, pw in zip(primes, best_pows)))) diff --git a/111_primes_with_runs.py b/111_primes_with_runs.py new file mode 100644 index 0000000..b0c202c --- /dev/null +++ b/111_primes_with_runs.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +from itertools import combinations, product + +def primes(n): + sieve = [True] * n + for p in range(2, int(n**0.5)+1): + if not sieve[p]: + continue + for i in range(p**2, n, p): + sieve[i] = False + return [False, False] + sieve[2:] + + +def is_prime(n): + for p in range(2, int(n**0.5)+1): + if sieve[p] and n%p==0: + return False + return True + +digs = 10 +sieve = primes(10**6) + +ts = 0 + +for dig in range(10): + c = 0 + s = 0 + num = str(dig) * digs + for rp in range(1,digs): + for comb in combinations(range(digs), rp): + if dig == 0 and comb[0] != 0: + continue + for perm in product(range(10), repeat=rp): + n = num + for i, d in zip(comb, perm): + n = n[:i] + str(d) + n[i+1:] + if is_prime(int(n)) and n[0] != "0": + c += 1 + s += int(n) + if c: + break + ts += s + #print("{} {} {:3} {}".format(dig, digs-rp, c, s)) + +print(ts) diff --git a/112_bouncy_numbers.py b/112_bouncy_numbers.py new file mode 100644 index 0000000..8a24ff1 --- /dev/null +++ b/112_bouncy_numbers.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# Brute force + +def main(x): + i = 100 + bc = 0 + while 100*bc // i != x: + i += 1 + bc += is_bouncy(i) + return i + +def is_bouncy(n): + n = list(str(n)) + s = sorted(n) + return n != s and n[::-1] != s + +print(main(99)) diff --git a/113_non-bouncy_numbers.py b/113_non-bouncy_numbers.py new file mode 100644 index 0000000..3358416 --- /dev/null +++ b/113_non-bouncy_numbers.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +from math import factorial + +def main(k): + n = 10 + ascend = binomial(n+k-1, k) + descnd = sum(binomial(n+i-1, i) for i in range(1,k+1)) + repeat = n*k + 1 # why 1 + return ascend + descnd - repeat + +def binomial(n, k): + return factorial(n) // (factorial(k)*factorial(n-k)) + +#print(main(6)) +#print(main(10)) +print(main(100)) diff --git a/114_counting_block_I.py b/114_counting_block_I.py new file mode 100644 index 0000000..bd48390 --- /dev/null +++ b/114_counting_block_I.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +# p -> recursive with lookup table +# p2 -> count individual combs, add squares, got from forum + +def p(n, tbl=False): + if n < 3: + return 1 + if tbl==False: + tbl = [] + if n-3 >= len(tbl): + r = 2*p(n-1, tbl) - p(n-2,tbl) + p(n-4, tbl) + tbl.append(r) + return tbl[n-3] + +def p2(n): + if n < 3: + return 1 + rd = 1 + b1 = b2 = 0 + b3 = 1 + for i in range(3,n): + b = b3 + b3 += b2 + b2 = b1 + b1 = rd + rd += b + return rd+b1+b2+b3 + +print(p(50)) diff --git a/115_counting_block_II.py b/115_counting_block_II.py new file mode 100644 index 0000000..3a6e8fb --- /dev/null +++ b/115_counting_block_II.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +# See 144 + +def main(m, bound): + n = m + tbl = [] + while p(m, n, tbl) < bound: n += 1 + return n, p(m, n, tbl) + +def p(m, n, tbl=False): + if n < m: + return 1 + if tbl==False: + tbl = [] + if n-m >= len(tbl): + r = 2*p(m, n-1, tbl) - p(m, n-2,tbl) + p(m, n-m-1, tbl) + tbl.append(r) + return tbl[n-m] + +def p2(m, n): + #doesnt work why? + if n < m: + return 1 + matrix = [1]+[0]*m + matrix[-1] = 1 + for _ in range(3,n): + bm = matrix[-1] + for i in range(m, 0, -1): + matrix[i] = matrix[i-1] + matrix[-1] += bm + matrix[0] += bm + return sum(matrix) + +print(main(50, 10**6)[0]) diff --git a/116_red_green_blue_tiles.py b/116_red_green_blue_tiles.py new file mode 100644 index 0000000..0c56528 --- /dev/null +++ b/116_red_green_blue_tiles.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# Modified 115 + +def main(n): + return p(2, n) + p(3, n) + p(4, n) - 3 + +def p(m, n, tbl=False): + if n < m: + return 1 + if tbl==False: + tbl = [] + if n-m >= len(tbl): + r = p(m, n-1, tbl) + p(m, n-m, tbl) + tbl.append(r) + return tbl[n-m] + +print(main(50)) diff --git a/117_red_green_blue_tilesII.py b/117_red_green_blue_tilesII.py new file mode 100644 index 0000000..c43e2d7 --- /dev/null +++ b/117_red_green_blue_tilesII.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +# See 116 + +def p(ms, n, tbl=False): + if n < min(ms): + return n>=0 + if tbl==False: + tbl = [] + if n-min(ms) >= len(tbl): + r = p(ms, n-1, tbl) + sum(p(ms, n-m, tbl) for m in ms) + tbl.append(r) + return tbl[n-min(ms)] + +print(p((2,3,4), 50)) diff --git a/118_pandigital_prime_sets.py b/118_pandigital_prime_sets.py new file mode 100644 index 0000000..0c9ecca --- /dev/null +++ b/118_pandigital_prime_sets.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +def primes(n): + sieve = [True] * n + for p in range(2, n): + if not sieve[p]: + continue + for i in range(p**2, n, p): + sieve[i] = False + return [False]*2 + sieve[2:] + +sieve = primes(10**7) + +def is_prime(n): + if n >= 10**7: + return heuristic(n) + return sieve[n] + +def heuristic(n): + for i in range(2, int(n**0.5)+1): #slow and lazy + if sieve[i] and n%i==0: + return False + return True + +def num(digs = set(range(1,10)), n=0, id=[]): + c = 0 + for d in [i for i in digs if i>n]: + c += dig(digs-{d}, d, d, id) + return c + +def dig(digs, n, p, id): + c = check(p, digs, n, id) + for d in digs: + c += dig(digs-{d}, n, 10*p + d, id) + return c + +def check(p, digs, n, id): + if len(digs) > 0 and max(digs) < n: + return 0 + if not is_prime(p): + return 0 + if len(digs) == 0: + return 1 + return num(digs, n, id) + +print(num()) diff --git a/119_digit_power_sum.py b/119_digit_power_sum.py new file mode 100644 index 0000000..007ffe8 --- /dev/null +++ b/119_digit_power_sum.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +# quick and dirty solution + +from math import sqrt, log10 + +def main(n): + a = 2 + nums = [] + while len(nums) < n or a < nums[-1]**(1.0/pw): + an, pw = check(a, nums*(len(nums)>=n)) + a += 1 + if an: + nums += an + nums = sorted(nums)[:n] + return nums[-1] + +def check(a, nums): + pw = int((a/9) * (1/log10(a))) + pw = 2 if pw<2 else pw + n = a**pw + r = [] + while len(str(n)) <= a and (not nums or n < nums[-1]): + if digsum(n) == a: + r.append(n) + n *= a + return r, pw + +def digsum(n): + return sum(map(int, str(n))) + +#print(main(2)) +#print(main(10)) +print(main(30))