def is_prime(n):
if n < 5:
return n == 2 or n == 3
elif n % 2 == 0 or n % 3 == 0:
return False
for i in range(5, int(n**0.5)+1, 6):
if n % i == 0 or n % (i+2) == 0:
return False
return True
Solutions to Project Euler’s second 50 problems
algorithm
project euler
python
numba
These are codes to solve the second 50 problems in Project Euler. These python codes will give solutions in less than 1 second. This is achieved by using the excellent numba package.
Problem 51
%%time
def problem51(max_digits=6):
= [[i, j, k] for i in range(6) for j in range(i+1, 6)
position_list for k in range(j+1, 6)]
for origin in range(10**(max_digits-3)):
for position in position_list:
= 0 if position[0] == 0 else 1
start_digit = start_digit
fail_count = []
answer for digit in range(start_digit, 10):
= "{:0{}d}".format(origin, max_digits-3)
origin_str = [str(digit)] * 6
expanded_digits 0]] = origin_str[0]
expanded_digits[position[1]] = origin_str[1]
expanded_digits[position[2]] = origin_str[2]
expanded_digits[position[= int("".join(expanded_digits))
generated_number if is_prime(generated_number) == False:
+= 1
fail_count if fail_count == 3:
break
else:
answer.append(generated_number)if len(answer) == 8:
return answer[0]
print(problem51())
121313
CPU times: user 40 ms, sys: 0 ns, total: 40 ms
Wall time: 40.9 ms
Problem 52
%%time
def problem52(limit=10**7):
for i in range(1, limit):
= sorted(str(i))
sorted_i if sorted_i == sorted(str(2*i)):
if sorted_i == sorted(str(3*i)):
if sorted_i == sorted(str(4*i)):
if sorted_i == sorted(str(5*i)):
if sorted_i == sorted(str(6*i)):
return i
print(problem52())
142857
CPU times: user 208 ms, sys: 0 ns, total: 208 ms
Wall time: 205 ms
Problem 53
from math import factorial
%%time
def problem53():
= 0
count for n in range(23, 101):
for r in range(1, n):
if factorial(n) // (factorial(r) * factorial(n-r)) > 10**6:
+= 1
count return count
print(problem53())
4075
CPU times: user 12 ms, sys: 0 ns, total: 12 ms
Wall time: 9.28 ms
Problem 54
from urllib.request import urlopen
= 'https://projecteuler.net/project/resources/p054_poker.txt'
url with urlopen(url) as response:
= response.read().decode()
DATA
def get_rank_value(hand):
= dict(zip('23456789TJQKA', range(13)))
CARD_TO_VALUE = ['Royal Flush', 'Straight Flush', 'Four of a Kind',
RANK_LIST 'Full House', 'Flush', 'Straight', 'Three of a Kind',
'Two Pairs', 'One Pair', 'High Card']
= dict(zip(RANK_LIST, range(9,-1,-1)))
RANK
= [CARD_TO_VALUE[card[0]] for card in hand]
cards = len(set([card[1] for card in hand])) == 1
is_flush = sorted([(cards.count(card), card) for card in set(cards)])
card_freqs = len(card_freqs)
n_cards = sum([card_freqs[i][1]*10**(2*i) for i in range(n_cards)])
value if card_freqs[-1][0] == 4:
return (RANK['Four of a Kind'], value)
elif card_freqs[-1][0] == 3:
if n_cards == 2:
return (RANK['Full House'], value)
else:
return (RANK['Three of a Kind'], value)
elif card_freqs[-1][0] == 2:
if n_cards == 3:
return (RANK['Two Pairs'], value)
else:
return (RANK['One Pair'], value)
elif (((card_freqs[4][1] - card_freqs[0][1]) == 4) or
4][1] == CARD_TO_VALUE['A'] and
((card_freqs[0][1] == CARD_TO_VALUE['2'] and
card_freqs[3][1] == CARD_TO_VALUE['5']))):
card_freqs[if is_flush:
if card_freqs[0][1] == CARD_TO_VALUE['A']:
return (RANK['Royal Flush'], value)
else:
return (RANK['Straight Flush'], value)
else:
return (RANK['Straight'], value)
elif is_flush:
return (RANK['Flush'], value)
else:
return (RANK['High Card'], value)
%%time
def problem54():
= DATA.strip().split('\n')
lines = 0
count for line in lines:
= line.split()
cards = cards[:5]
player_1 = cards[5:]
player_2 if get_rank_value(player_1) > get_rank_value(player_2):
+= 1
count return count
print(problem54())
376
CPU times: user 20 ms, sys: 0 ns, total: 20 ms
Wall time: 17.8 ms
Problem 55
%%time
def problem55(limit=10000):
= 0
c for i in range(limit):
= i
n = int(str(n)[::-1])
n_t = True
is_Lychrel for j in range(49):
= n + n_t
n = int(str(n)[::-1])
n_t if n == n_t:
= False
is_Lychrel break
if is_Lychrel:
+= 1
c return c
print(problem55())
249
CPU times: user 40 ms, sys: 0 ns, total: 40 ms
Wall time: 40.7 ms
Problem 56
%%time
def problem56():
= 0
max_digital_sum for a in range(100):
for b in range(100):
= sum([int(x) for x in str(a**b)])
d_sum if d_sum > max_digital_sum:
= d_sum
max_digital_sum return max_digital_sum
print(problem56())
972
CPU times: user 128 ms, sys: 0 ns, total: 128 ms
Wall time: 130 ms
Problem 57
from fractions import Fraction
%%time
def problem57():
= 2 + Fraction(1, 2)
x = 0
count for i in range(1000):
= x - 1
y if len(str(y.numerator)) > len(str(y.denominator)):
+= 1
count = 2 + Fraction(1, x)
x return count
print(problem57())
153
CPU times: user 40 ms, sys: 0 ns, total: 40 ms
Wall time: 40.9 ms
Problem 58
from numba import jit
@jit
def is_prime(n):
if n < 5:
return n == 2 or n == 3
elif n % 2 == 0 or n % 3 == 0:
return False
for i in range(5, int(n**0.5)+1, 6):
if n % i == 0 or n % (i+2) == 0:
return False
return True
%%time
@jit
def problem58():
= 1
x = 0
gap = 0
n_prime_x10 = 1
n_x while True:
= gap + 2
gap for i in range(3):
= x + gap
x if is_prime(x):
+= 10
n_prime_x10 = x + gap
x += 4
n_x if n_prime_x10 < n_x:
return int(x**0.5)
print(problem58())
26241
CPU times: user 216 ms, sys: 4 ms, total: 220 ms
Wall time: 220 ms
Problem 59
from urllib.request import urlopen
= 'https://projecteuler.net/project/resources/p059_cipher.txt'
url with urlopen(url) as response:
= response.read().decode() DATA
%%time
def problem59():
= list(map(lambda x: int(x), DATA.rstrip().split(',')))
cipher = len(cipher)
length = ord('a')
ord_a for i in range(ord_a, ord_a+26):
for j in range(ord_a, ord_a+26):
for k in range(ord_a, ord_a+26):
= ([i, j, k] * (length//3+1))[:length]
key = bytes([x^y for x, y in zip(cipher, key)])
message if b'that' in message and b'have' in message:
return sum([ord(x) for x in message.decode()])
print(problem59())
107359
CPU times: user 332 ms, sys: 0 ns, total: 332 ms
Wall time: 333 ms
Problem 60
import numpy as np
from numba import jit, int8, int64
@jit(int8[:](int64))
def create_sieve_of_halfprimes(n):
= np.ones(n//2, dtype=np.int8)
sieve for i in range(3, int(n**0.5)+1, 2):
if sieve[i//2]:
*i//2::i] = 0
sieve[ireturn sieve
@jit(int8[:,:](int8[:], int64[:]))
def create_check_matrix(sieve, primes):
= np.zeros((len(primes), len(primes)), dtype=np.int8)
check_matrix for i1 in range(len(primes)):
for i2 in range(i1+1, len(primes)):
= (primes[i1]
half_prime12 * 10**(int(np.log10(primes[i2]))+1)
+ primes[i2]) // 2
if sieve[half_prime12]:
= (primes[i2]
half_prime21 * 10**(int(np.log10(primes[i1]))+1)
+ primes[i1]) // 2
if sieve[half_prime21]:
= 1
check_matrix[i1, i2] return check_matrix
@jit(int64(int64[:], int8[:,:]))
def find_answer(primes, check_matrix):
for a1 in range(len(primes)):
for a2 in range(a1+1, len(primes)):
if check_matrix[a1, a2]:
for a3 in range(a2+1, len(primes)):
if check_matrix[a2, a3] and check_matrix[a1, a3]:
for a4 in range(a3+1, len(primes)):
if (check_matrix[a3, a4] and check_matrix[a2, a4]
and check_matrix[a1, a4]):
for a5 in range(a4+1, len(primes)):
if (check_matrix[a4, a5]
and check_matrix[a3, a5]
and check_matrix[a2, a5]
and check_matrix[a1, a5]):
return (primes[a1] + primes[a2]
+ primes[a3] + primes[a4]
+ primes[a5])
return 0
%%time
def problem60(limit=10**4):
= create_sieve_of_halfprimes(limit**2)
sieve = 2*np.nonzero(sieve[:limit//2])[0][1:] + 1
primes = create_check_matrix(sieve, primes)
check_matrix return find_answer(primes, check_matrix)
print(problem60())
26033
CPU times: user 296 ms, sys: 4 ms, total: 300 ms
Wall time: 298 ms
Problem 61
def create_polygonal_numbers(k):
= []
l = n = 1
p while p < 10000:
if p >= 1000:
l.append(p)= n + 1
n = n * ((k-2)*n - k + 4) // 2
p return l
def check(a, b, c, d, e, f, polygonal_dict):
= a*100 + b
ab = b*100 + c
bc = c*100 + d
cd = d*100 + e
de = e*100 + f
ef = f*100 + a
fa for i1 in polygonal_dict[ab]:
for i2 in polygonal_dict[bc]:
for i3 in polygonal_dict[cd]:
for i4 in polygonal_dict[de]:
for i5 in polygonal_dict[ef]:
for i6 in polygonal_dict[fa]:
if len(set([i1,i2,i3,i4,i5,i6])) == 6:
return True
return False
%%time
def problem61():
= dict()
polygonal_dict for k in range(3, 9):
for n in create_polygonal_numbers(k):
if n not in polygonal_dict:
= [k]
polygonal_dict[n] else:
polygonal_dict[n].append(k)
= dict()
cyclic for n in polygonal_dict:
= (n//100, n%100)
a, b if b < 10:
continue
if a not in cyclic:
= [b]
cyclic[a] else:
cyclic[a].append(b)
for a in cyclic:
for b in cyclic[a]:
if b not in cyclic:
continue
for c in cyclic[b]:
if c not in cyclic:
continue
for d in cyclic[c]:
if d not in cyclic:
continue
for e in cyclic[d]:
if e not in cyclic:
continue
for f in cyclic[e]:
if f not in cyclic:
continue
if a not in cyclic[f]:
continue
if check(a, b, c, d, e, f, polygonal_dict):
return sum([a,b,c,d,e,f]) * 101
print(problem61())
28684
CPU times: user 4 ms, sys: 0 ns, total: 4 ms
Wall time: 741 µs
Problem 62
from collections import Counter
%%time
def problem62():
= 1
k while True:
= []
cubes for n in range(int(int('1'*k)**(1/3))+1, int(int('9'*k)**(1/3))+1):
**3)
cubes.append(n= [''.join(sorted(str(x))) for x in cubes]
arranged_cubes = Counter(arranged_cubes)
counter for c in list(counter):
if counter[c] == 5:
return cubes[arranged_cubes.index(c)]
+= 1
k
print(problem62())
127035954683
CPU times: user 28 ms, sys: 0 ns, total: 28 ms
Wall time: 28.3 ms
Problem 63
%%time
def problem63():
= 1
n = 1
c while len(str(9**n)) >= n:
for i in range(2, 10):
if i**n >= 10**(n-1):
+= 1
c += 1
n return c
print(problem63())
49
CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 141 µs
Problem 64
def count_period(n):
if n == int(n**0.5)**2:
return 0
= 0
b = 1
c = []
l while True:
if (b,c) in l:
return len(l) - l.index((b,c))
l.append((b,c))= int((n**0.5 + b) / c) * c - b
b = (n - b**2) // c c
%%time
def problem64(limit=10**4):
= 0
c for i in range(2, limit+1):
if count_period(i) % 2 == 1:
+= 1
c return c
print(problem64())
1322
CPU times: user 420 ms, sys: 0 ns, total: 420 ms
Wall time: 419 ms
Problem 65
from fractions import Fraction
%%time
def problem65():
= [2]
fraction_list for i in range(1, 34):
+= [1, 2*i, 1]
fraction_list = Fraction(fraction_list[-1])
rational_approx for a in fraction_list[-2::-1]:
= a + 1 / rational_approx
rational_approx return sum([int(x) for x in str(rational_approx.numerator)])
print(problem65())
272
CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 1.02 ms
Problem 66
from fractions import Fraction
def diophantine_solution(D):
if D == int(D**0.5)**2:
return 1
= 0
b = 1
c = a0 = int(D**0.5)
a = []
fraction_list while True:
= int((D**0.5 + b) / c)
a if a == 2*a0:
break
fraction_list.append(a)= a*c - b
b = (D - b**2) // c
c = Fraction(fraction_list[-1])
rational_approx for a in fraction_list[-2::-1]:
= a + 1 / rational_approx
rational_approx if rational_approx.numerator**2 - D*rational_approx.denominator**2 == 1:
return rational_approx.numerator
= rational_approx + a0
rational_approx for a in fraction_list[::-1]:
= a + 1 / rational_approx
rational_approx return rational_approx.numerator
%%time
def problem66(limit=1000):
= 3
x_max = 2
d_max for i in range(3, limit+1):
= diophantine_solution(i)
x if x > x_max:
= x
x_max = i
d_max return d_max
print(problem66())
661
CPU times: user 96 ms, sys: 0 ns, total: 96 ms
Wall time: 93.3 ms
Problem 67
from urllib.request import urlopen
= 'https://projecteuler.net/project/resources/p067_triangle.txt'
url with urlopen(url) as response:
= response.read().decode() DATA
%%time
def problem67():
= [[int(y) for y in x.split()] for x in DATA.rstrip().split('\n')]
triangle = [59]
route for i, row in enumerate(triangle[1:]):
= [row[0] + route[0]] \
current + [x + max(route[j], route[j+1]) for j, x in enumerate(row[1:-1])] \
+ [row[-1] + route[-1]]
= current
route return max(route)
print(problem67())
7273
CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 2.3 ms
Problem 68
%%time
def problem68():
= []
solutions = 10
a for b in range(1, 10):
for c in range(1, 10):
if b == c:
continue
for d in range(1, 10):
if d in [b, c]:
continue
= a + b - d
e if e < 1 or e > 9 or e in [b, c, d]:
continue
for f in range(1, 10):
if f in [b, c, d, e]:
continue
= c + d - f
g if g < 1 or g > 9 or g in [b, c, d, e, f]:
continue
for h in range(1, 10):
if h in [b, c, d, e, f, g]:
continue
= e + f - h
i = g + h - b
j if i < 1 or j < 1 or i > 9 or j > 9:
continue
if len(set([a,b,c,d,e,f,g,h,i,j])) == 10:
solutions.append([a,b,c,d,c,e,f,e,g,h,g,i,j,i,b])= []
ordered_solutions for solution in solutions:
= solution.index(min(solution[0], solution[3],
i_min 6], solution[9], solution[12]))
solution[= solution[i_min:] + solution[:i_min]
ordered_solution = int(''.join(
ordered_solution_to_int str(x) for x in ordered_solution]))
[
ordered_solutions.append(ordered_solution_to_int)return max(ordered_solutions)
print(problem68())
6531031914842725
CPU times: user 0 ns, sys: 4 ms, total: 4 ms
Wall time: 1.34 ms
Problem 69
import numpy as np
%%time
def problem69(limit=10**6):
= np.ones(limit+1)
sieve = np.ones(limit+1)
n_per_phi_n_list for i in range(2, int(limit**0.5)+1):
if sieve[i] == 1:
= 0
sieve[i::i] *= i / (i-1)
n_per_phi_n_list[i::i] return np.argmax(n_per_phi_n_list)
print(problem69())
510510
CPU times: user 28 ms, sys: 0 ns, total: 28 ms
Wall time: 27.5 ms
Problem 70
import numpy as np
from numba import jit
@jit
def create_sieve(n):
= np.ones(n, dtype=np.int8)
sieve 0] = sieve[1] = 0
sieve[4::2] = 0
sieve[for i in range(3, int(n**0.5)+1, 2):
if sieve[i]:
*i::i] = 0
sieve[ireturn sieve
%%time
def problem70(limit=10**7):
= create_sieve(limit)
sieve = np.nonzero(sieve)[0]
prime_list = len(prime_list)
nb_primes = 87109
n_min = 87109 / 79180
ratio_min = np.nonzero((prime_list ** 2) >= 10**7)[0][0]-1
i_max for i in range(i_max, -1, -1):
if prime_list[i] / (prime_list[i]-1) >= ratio_min:
break
for j in range(i+1, nb_primes):
= prime_list[i] * prime_list[j]
i_times_j if i_times_j >= 10**7:
break
= (prime_list[i]-1) * (prime_list[j]-1)
phi_i_times_j = i_times_j / phi_i_times_j
ratio if ratio < ratio_min:
if sorted(str(i_times_j)) == sorted(str(phi_i_times_j)):
= i_times_j
n_min = ratio
ratio_min return n_min
print(problem70())
8319823
CPU times: user 280 ms, sys: 0 ns, total: 280 ms
Wall time: 279 ms
Problem 71
from fractions import Fraction
%%time
def problem71(limit=10**6):
= 5
d_min = 2
n_min for d in range(2, limit+1):
= 3 * d // 7
n if d % 7 == 0:
= n-1
n if n * d_min > d * n_min:
= n
n_min = d
d_min return Fraction(n_min, d_min).numerator
print(problem71())
428570
CPU times: user 220 ms, sys: 0 ns, total: 220 ms
Wall time: 219 ms
Problem 72
import numpy as np
from numba import jit
%%time
@jit
def problem72(limit=10**6):
= np.ones(limit+1)
sieve = np.arange(limit+1)
phi_n_list 1] = 0
phi_n_list[for i in range(2, limit+1):
if sieve[i] == 1:
*i::i] = 0
sieve[i*= (i-1)
phi_n_list[i::i] //= i
phi_n_list[i::i] return sum(phi_n_list)
print(problem72())
303963552391
CPU times: user 360 ms, sys: 0 ns, total: 360 ms
Wall time: 359 ms
Problem 73
from numba import jit
@jit
def count_Stern_Brocot(limit, left_n, left_d, right_n, right_d):
= left_n + right_n
mid_n = left_d + right_d
mid_d if mid_d > limit:
return 0
else:
= 1
count += count_Stern_Brocot(limit, left_n, left_d, mid_n, mid_d)
count += count_Stern_Brocot(limit, mid_n, mid_d, right_n, right_d)
count return count
%%time
def problem73(limit=12000):
return count_Stern_Brocot(12000, 1, 3, 1, 2)
print(problem73())
7295372
CPU times: user 124 ms, sys: 0 ns, total: 124 ms
Wall time: 124 ms
Problem 74
from math import factorial
from itertools import permutations
def count_permuation(n):
= set(permutations(str(n)))
p if str(n)[0] == '1':
= '0' + str(n)[1:]
new_str = p.union(set(permutations(new_str)))
p if str(n)[:2] == '11':
= '00' + str(n)[2:]
new_str = p.union(set(permutations(new_str)))
p if str(n)[:3] == '111':
= '000' + str(n)[3:]
new_str = p.union(set(permutations(new_str)))
p if str(n)[:4] == '1111':
= '0000' + str(n)[4:]
new_str = p.union(set(permutations(new_str)))
p if str(n)[:5] == '11111':
= p.add(str(n)[5:]+'00000')
p = 0
c for e in p:
if e[0] != '0':
+= 1
c return c
%%time
def problem74():
= [factorial(x) for x in range(10)]
fac = [0] * 2200000
a = []
answer_list for i1 in range(10):
for i2 in range(i1, 10):
for i3 in range(i2, 10):
for i4 in range(i3, 10):
for i5 in range(i4, 10):
for i6 in range(i5, 10):
= i1*10**5+i2*10**4+i3*1000+i4*100+i5*10+i6
i = []
chain = i
j while (a[j] == 0) and (j not in chain):
chain.append(j)= 0
s = j
jr while jr != 0:
+= fac[jr % 10]
s //= 10
jr = s
j if j in chain:
for t in range(len(chain)):
= len(chain) - t
a[chain[t]] if chain[t] == j:
break
for t1 in range(t+1, len(chain)):
= len(chain) - t
a[chain[t1]] else:
for t, k in enumerate(chain):
= len(chain) - t + a[j]
a[k] if a[i] == 60:
answer_list.append(i)return sum([count_permuation(answer) for answer in answer_list])
print(problem74())
402
CPU times: user 20 ms, sys: 0 ns, total: 20 ms
Wall time: 18.7 ms
Problem 75
from numba import jit
@jit
def gcd(m, n):
if m == 0:
return n
return gcd(n % m, m)
%timeit
def problem75(limit=1500000):
= [0] * (limit + 1)
d for n in range(1, 1000):
for m in range(n+1, 1000, 2):
if gcd(m, n) != 1:
continue
= 2 * m * (m + n)
L = limit // L
k_max for k in range(1, k_max+1):
*k] += 1
d[L= 0
c for i in range(limit+1):
if d[i] == 1:
+= 1
c return c
print(problem75())
161667
Problem 76
import numpy as np
%%time
def problem76():
= np.zeros((101, 101), dtype=np.int)
A for i in range(1, 101):
for j in range(1, i+1):
= 1
A[i, j] for k in range(j, i//2+1):
+= A[i-k, k]
A[i, j] return A[100, 1] - 1
print(problem76())
190569291
CPU times: user 24 ms, sys: 0 ns, total: 24 ms
Wall time: 21.3 ms
Problem 77
import numpy as np
def is_prime(n):
if n < 5:
return n == 2 or n == 3
elif n % 2 == 0 or n % 3 == 0:
return False
for i in range(5, int(n**0.5)+1, 6):
if n % i == 0 or n % (i+2) == 0:
return False
return True
%%time
def problem77():
= np.zeros((101, 101), dtype=np.int)
A for i in range(1, 101):
for j in range(1, i+1):
if is_prime(i):
= 1
A[i, j] for k in range(j, i//2+1):
if is_prime(k):
+= A[i-k, k]
A[i, j] if A[i, j] > 5000 + is_prime(i):
return i
print(problem77())
71
CPU times: user 20 ms, sys: 0 ns, total: 20 ms
Wall time: 20.5 ms
Problem 78
from numba import jit
%%time
@jit
def problem78(limit=60000):
= [0] * limit
p 0] = 1
p[1] = 1
p[for i in range(2, limit):
= 1
k = 1
s = 0
g_k while True:
+= 2*k - 1
g_k if g_k > i:
break
= p[i] + s*p[i-g_k]
p[i] += k
g_k if g_k > i:
break
= p[i] + s*p[i-g_k]
p[i] += 1
k = -s
s = p[i] % 10**6
p[i] if p[i] == 0:
return i
print(problem78())
55374
CPU times: user 100 ms, sys: 0 ns, total: 100 ms
Wall time: 102 ms
Problem 79
from urllib.request import urlopen
from itertools import permutations, combinations
= 'https://projecteuler.net/project/resources/p079_keylog.txt'
url with urlopen(url) as response:
= response.read().decode() DATA
%%time
def problem79():
for p in permutations(''.join(sorted(list(set(DATA) - {'\n'})))):
= ''.join(p)
passcode = [''.join(x) for x in combinations(passcode, 3)]
passcode_keys = True
flag for key in DATA.split():
if key not in passcode_keys:
= False
flag break
if flag == True:
return passcode
print(problem79())
73162890
CPU times: user 300 ms, sys: 0 ns, total: 300 ms
Wall time: 300 ms
Problem 80
from decimal import getcontext, Decimal
%%time
def problem80():
= 102
getcontext().prec = 0
s for i in range(1, 101):
if i not in [y**2 for y in range(1, 11)]:
+= sum([int(x) for x in str(Decimal(i).sqrt())[:101]
s if x != '.'])
return s
print(problem80())
40886
CPU times: user 4 ms, sys: 0 ns, total: 4 ms
Wall time: 4.47 ms
Problem 81
from urllib.request import urlopen
= 'https://projecteuler.net/project/resources/p081_matrix.txt'
url with urlopen(url) as response:
= response.read().decode() DATA
%%time
def problem81():
= [[int(y) for y in x.split(',')] for x in DATA.split()]
matrix = [[0]*80]*80
path_sum for i in range(80):
for j in range(80):
if i == 0 and j == 0:
= 0
min_path elif i == 0:
= path_sum[i][j-1]
min_path elif j == 0:
= path_sum[i-1][j]
min_path else:
= min(path_sum[i][j-1], path_sum[i-1][j])
min_path = matrix[i][j] + min_path
path_sum[i][j] return path_sum[79][79]
print(problem81())
427337
CPU times: user 4 ms, sys: 0 ns, total: 4 ms
Wall time: 3.94 ms
Problem 82
from urllib.request import urlopen
import numpy as np
= 'https://projecteuler.net/project/resources/p082_matrix.txt'
url with urlopen(url) as response:
= response.read().decode() DATA
%%time
def problem82():
= np.array([[int(y) for y in x.split(',')] for x in DATA.split()],
matrix ='uint16')
dtype= np.zeros((80, 80), dtype='uint32')
path_sum = np.zeros((80, 80), dtype='uint32')
min_path
for j in range(80):
for i in range(80):
if j == 0:
= [0]
min_path else:
= [path_sum[i, j-1]]
min_path for k in range(80):
if k < i:
sum()
min_path.append(matrix[k:i, j].+ path_sum[k, j-1])
if k > i:
+1:k+1, j].sum()
min_path.append(matrix[i+ path_sum[k, j-1])
= matrix[i, j] + min(min_path)
path_sum[i, j] return path_sum[:,79].min()
print(problem82())
260324
CPU times: user 956 ms, sys: 0 ns, total: 956 ms
Wall time: 958 ms
Problem 83
from urllib.request import urlopen
import numpy as np
= 'https://projecteuler.net/project/resources/p083_matrix.txt'
url with urlopen(url) as response:
= response.read().decode()
DATA
def update(i, j, path_sum, matrix, inf):
= [inf]
min_around if i > 0:
-1, j])
min_around.append(path_sum[iif i < 79:
+1, j])
min_around.append(path_sum[iif j > 0:
-1])
min_around.append(path_sum[i, jif j < 79:
+1])
min_around.append(path_sum[i, j= min(min_around) + matrix[i, j] path_sum[i, j]
%%time
def problem83():
= np.array([[int(y) for y in x.split(',')] for x in DATA.split()],
matrix ='uint16')
dtype
= np.iinfo(np.uint32).max // 2
inf = np.zeros((80, 80), dtype='uint32')
path_sum = inf
path_sum[:] 0, 0] = matrix[0, 0]
path_sum[
= np.zeros((80, 80), dtype='bool')
visited 0, 0] = True
visited[0, 1, path_sum, matrix, inf)
update(1, 0, path_sum, matrix, inf)
update(
while not visited[79, 79]:
= np.unravel_index(np.ma.argmin(
i, j 80, 80))
np.ma.MaskedArray(path_sum, visited)), (= True
visited[i, j] if i > 0 and not visited[i-1, j]:
-1, j, path_sum, matrix, inf)
update(iif i < 79 and not visited[i+1, j]:
+1, j, path_sum, matrix, inf)
update(iif j > 0 and not visited[i, j-1]:
-1, path_sum, matrix, inf)
update(i, jif j < 79 and not visited[i, j+1]:
+1, path_sum, matrix, inf)
update(i, jreturn path_sum[79, 79]
print(problem83())
425185
CPU times: user 360 ms, sys: 0 ns, total: 360 ms
Wall time: 359 ms
Problem 84
from random import randint
%%time
def problem84():
= 10
jail = 30
g2j = [2, 17, 33]
cc = [7, 22, 36]
ch = 0
double = [0] * 40
table = 0
i for j in range(100000):
= randint(1, 4)
dice1 = randint(1, 4)
dice2 if dice1 == dice2:
+= 1
double else:
= 0
double if double == 3:
= jail
i else:
= (i + dice1 + dice2) % 40
i if i in cc:
= randint(1, 16)
cc_open if cc_open == 1:
= 0
i elif cc_open == 2:
= jail
i if i in ch:
= randint(1, 16)
ch_open if ch_open == 1:
= 0
i elif ch_open == 2:
= jail
i elif ch_open == 3:
= 11
i elif ch_open == 4:
= 24
i elif ch_open == 5:
= 39
i elif ch_open == 6:
= 5
i elif ch_open in [7, 8]:
if i == ch[0]:
= 15
i elif i == ch[1]:
= 25
i else:
= 5
i elif ch_open == 9:
if i == ch[1]:
= 28
i else:
= 12
i elif ch_open == 10:
= (i-3)%40
i if i == g2j:
= jail
i += 1
table[i] = sorted(table, reverse=True)[:3]
a, b, c return '{:02d}{:02d}{:02d}'.format(table.index(a),
table.index(b), table.index(c))
print(problem84())
101516
CPU times: user 232 ms, sys: 0 ns, total: 232 ms
Wall time: 234 ms
Problem 85
%%time
def problem85():
= []
areas = []
rectangles
for n in range(1, 3000):
for m in range(n, 3000//n):
* m)
areas.append(n * m * (n+1) * (m+1) // 4)
rectangles.append(n
= [int(abs(r - 2e6)) for r in rectangles]
ds return areas[ds.index(min(ds))]
print(problem85())
2772
CPU times: user 4 ms, sys: 0 ns, total: 4 ms
Wall time: 6.8 ms
Problem 86
from numba import jit
%%time
@jit
def problem86():
= 0
n_sol = 0
M while n_sol <= 10**6:
+= 1
M for a_plus_b in range(2, 2*M+1):
= M**2 + a_plus_b**2
min_square if min_square == (int(min_square**0.5)**2):
= max(1, a_plus_b-M)
b_min = a_plus_b//2
b_max += (b_max - b_min + 1)
n_sol return M
print(problem86())
1818
CPU times: user 84 ms, sys: 0 ns, total: 84 ms
Wall time: 83.7 ms
Problem 87
import numpy as np
from numba import jit
%%time
@jit
def problem87():
= 5*10**7-1
limit = int(limit**(1/2))
x_max = int(limit**(1/3))
y_max = int(limit**(1/4))
z_max = np.ones(x_max+1, dtype=np.bool)
sieve 0] = sieve[1] = 0
sieve[for i in range(2, int(limit**0.5)+1):
if sieve[i] == 1:
2*i::i] = 0
sieve[= np.nonzero(sieve[:x_max+1])[0]
x_list = np.nonzero(sieve[:y_max+1])[0]
y_list = np.nonzero(sieve[:z_max+1])[0]
z_list = np.zeros(limit+1, dtype=np.bool)
A for x in x_list:
for y in y_list:
for z in z_list:
= x**2 + y**3 + z**4
n if n <= limit:
= 1
A[n] return A.sum()
print(problem87())
1097343
CPU times: user 512 ms, sys: 4 ms, total: 516 ms
Wall time: 514 ms
Problem 88
%%time
def problem88():
= 12000
k_max = 2 * k_max
product_max = k_max // 4
a_max = k_max
m_max = 1
prod = [2*k_max] * (k_max+1)
mps 0] = mps[1] = 0
mps[for a in range(1, a_max//prod+1):
= a
prod for b in range(a, a_max//prod+1):
= a*b
prod for c in range(b, a_max//prod+1):
= a*b*c
prod for d in range(c, a_max//prod+1):
= a*b*c*d
prod for e in range(d, a_max//prod+1):
= a*b*c*d*e
prod for f in range(e, a_max//prod+1):
= a*b*c*d*e*f
prod for g in range(f, a_max//prod+1):
= a*b*c*d*e*f*g
prod for h in range(g, a_max//prod+1):
= a*b*c*d*e*f*g*h
prod for i in range(h, a_max//prod+1):
= a*b*c*d*e*f*g*h*i
prod for j in range(i, a_max//prod+1):
= a*b*c*d*e*f*g*h*i*j
prod for k in range(j, a_max//prod+1):
= a*b*c*d*e*f*g*h*i*j*k
prod = max(2, k)
l_min = k_max // (2*prod)
l_max for l in range(l_min,
+1):
l_maxfor m in range(l,
+1):
k_max= (a*b*c*d*e*f*g
prod *h*i*j*k*l*m)
= (a+b+c+d+e+f+g+h
s +i+j+k+l+m)
= prod - s + 13
kk if kk > k_max:
break
if prod < mps[kk]:
= prod
mps[kk] return sum(set(mps))
print(problem88())
7587457
CPU times: user 232 ms, sys: 0 ns, total: 232 ms
Wall time: 235 ms
Problem 89
from urllib.request import urlopen
= 'https://projecteuler.net/project/resources/p089_roman.txt'
url with urlopen(url) as response:
= response.read().decode()
DATA
def minimize_form(number):
= number.replace('VIIII', 'IX')
number = number.replace('IIII', 'IV')
number = number.replace('LXXXX', 'XC')
number = number.replace('XXXX', 'XL')
number = number.replace('DCCCC', 'CM')
number = number.replace('CCCC', 'CD')
number return number
%%time
def problem89():
return (sum([len(x) for x in DATA.split()])
- sum([len(minimize_form(x)) for x in DATA.split()]))
print(problem89())
743
CPU times: user 4 ms, sys: 0 ns, total: 4 ms
Wall time: 1.1 ms
Problem 90
from itertools import combinations, product
def check(square, pairs):
if (square[0], square[1]) in pairs or (square[1], square[0]) in pairs:
return True
else:
return False
%%time
def problem90():
= [set(x) | {'6', '9'} if ('6' in x or '9' in x)
arrangements else set(x) for x in combinations('0123456789', 6)]
= ['01', '04', '09', '16', '25', '36', '49', '64', '81']
squares = 0
c for dice1 in arrangements:
for dice2 in arrangements:
= list(product(dice1, dice2))
pairs = True
flag for square in squares:
if not check(square, pairs):
= False
flag break
if flag == True:
+= 1
c return c//2
print(problem90())
1217
CPU times: user 360 ms, sys: 0 ns, total: 360 ms
Wall time: 360 ms
Problem 91
from numba import jit
@jit
def problem91():
= 0
s for i in range(0, 51):
for j in range(0, i):
= i**2 + j**2
c for a in range(0, 51):
for b in range(0, 51):
if a == 0 and b == 0:
continue
if a == i and b == j:
continue
if a**2 + b**2 + (i-a)**2 + (j-b)**2 == c:
+= 1
s for k in range(1, 51):
if k**2 + k**2 == c + (i-k)**2 + (j-k)**2:
+= 1
s return 2*s + 50*50
print(problem91())
14234
Problem 92
from numba import jit
@jit
def make_sum_digits2_table():
= [0] * 10**7
sum_digits2_table = [x**2 for x in range(10)]
digits2 for i1 in range(10):
for i2 in range(10):
for i3 in range(10):
for i4 in range(10):
for i5 in range(10):
for i6 in range(10):
for i7 in range(10):
= (i1+i2*10+i3*100+i4*1000+i5*10000
num +i6*100000+i7*1000000)
= (digits2[i1]+digits2[i2]+digits2[i3]
sd2 +digits2[i4]+digits2[i5]
+digits2[i6]+digits2[i7])
= sd2
sum_digits2_table[num] return sum_digits2_table
%%time
@jit
def problem92():
= make_sum_digits2_table()
sum_digits2_table = [0] * 10**7
chain_end 1] = 1
chain_end[89] = 2
chain_end[for i in range(1, 10**7):
= i
j while chain_end[j] == 0:
= sum_digits2_table[j]
j = chain_end[j]
chain_end[i]
= 0
c for i in range(10**7):
if chain_end[i] == 2:
+= 1
c return c
print(problem92())
8581146
CPU times: user 432 ms, sys: 16 ms, total: 448 ms
Wall time: 451 ms
Problem 93
from itertools import combinations, permutations
from operator import add, truediv, mul, sub
%%time
def problem93():
= dict()
combos = [add, truediv, mul, sub,
ops lambda a, b: sub(b, a), lambda a, b: truediv(b, a)]
for four_digit in list(combinations(range(1, 10), 4)):
= [0]*10000
A for (a, b, c, d) in permutations(four_digit):
for op1 in ops:
for op2 in ops:
for op3 in ops:
try:
= op3(op2(op1(a,b),c),d)
num except ZeroDivisionError:
continue
if num > 0 and num - int(num) < 0.001:
int(num)] = 1
A[0] = 1
A[= A.index(0) - 1
combos[four_digit] = max(combos, key=combos.get)
max_combo return ''.join([str(x) for x in max_combo])
print(problem93())
1258
CPU times: user 304 ms, sys: 0 ns, total: 304 ms
Wall time: 303 ms
Problem 94
from numba import jit
%%time
@jit
def problem94():
= (10**9 - 2) // 6
n_max = 0
s for n in range(2, n_max+1):
= 3*n*n + 4*n + 1
h2 if h2 == int(h2**0.5)**2:
+= (6*n+2)
s = 3*n*n - 4*n + 1
h2 if h2 == int(h2**0.5)**2:
+= (6*n-2)
s = n_max+1
n = 3*n*n - 4*n + 1
h2 if h2 == int(h2**0.5)**2:
+= (6*n-2)
s return s
print(problem94())
518408346
CPU times: user 632 ms, sys: 8 ms, total: 640 ms
Wall time: 639 ms
Problem 95
import numpy as np
from numba import jit
@jit
def get_proper_sum(limit):
= np.ones(limit+1)
sieve = np.ones(limit+1, dtype=np.int32)
proper_sum = np.arange(limit+1)
current_n for p in range(2, int(limit**0.5)+1):
if sieve[p] == 1:
= 0
sieve[p::p] for n in range(p, limit+1, p):
= proper_sum[n]
temp while current_n[n] % p == 0:
//= p
current_n[n] = proper_sum[n]*p + temp
proper_sum[n] = (current_n != 1) + current_n
current_n = proper_sum * current_n - np.arange(limit+1)
proper_sum return proper_sum
%%time
@jit
def problem95():
= 10**6
limit = get_proper_sum(limit)
proper_sum = np.zeros(limit+1, dtype=np.int8)
checked > limit] = -1
checked[proper_sum == 1] = -1
checked[proper_sum 1] = -1
checked[= 0
len_max = 0
start_min for i in range(2, limit+1):
if checked[i] != 0:
continue
= i
next_i while checked[next_i] == 0:
= 1
checked[next_i] = proper_sum[next_i]
next_i if checked[next_i] == 1:
= i
j while j != next_i:
= -1
checked[j] = proper_sum[j]
j = 1
chain_len = next_i
chain_min = proper_sum[next_i]
j while j != next_i:
= -1
checked[j] += 1
chain_len if j < chain_min:
= j
chain_min = proper_sum[j]
j if chain_len > len_max:
= chain_len
len_max = chain_min
start_min else:
= i
j while checked[j] == 1:
= -1
checked[j] = proper_sum[j]
j return start_min
print(problem95())
14316
CPU times: user 808 ms, sys: 0 ns, total: 808 ms
Wall time: 808 ms
Problem 96
from urllib.request import urlopen
import numpy as np
= 'https://projecteuler.net/project/resources/p096_sudoku.txt'
url with urlopen(url) as response:
= response.read().decode()
DATA
def scan(sudoku):
for num in range(9):
for a in range(3):
for b in range(3):
if sudoku[a,b,:,:,num].sum() == 1:
= np.nonzero(sudoku[a,b,:,:,num])
c_list, d_list return a, b, c_list[0], d_list[0], num
for num in range(9):
for c in range(3):
for d in range(3):
if sudoku[:,:,c,d,num].sum() == 1:
= np.nonzero(sudoku[:,:,c,d,num])
a_list, b_list return a_list[0], b_list[0], c, d, num
for num in range(9):
for a in range(3):
for c in range(3):
if sudoku[a,:,c,:,num].sum() == 1:
= np.nonzero(sudoku[a,:,c,:,num])
b_list, d_list return a, b_list[0], c, d_list[0], num
for a in range(3):
for b in range(3):
for c in range(3):
for d in range(3):
if sudoku[a,b,c,d,:].sum() == 1:
= np.nonzero(sudoku[a,b,c,d,:])
num_list return a, b, c, d, num_list[0][0]
return 0, 0, 0, 0, -1
def fill(sudoku, a, b, c, d, num):
= 0
sudoku[a, b, :, :, num] = 0
sudoku[:, :, c, d, num] = 0
sudoku[a, :, c, :, num] = 0
sudoku[a, b, c, d, :] = 10
sudoku[a, b, c, d, num]
def scan_and_fill(sudoku):
= scan(sudoku)
a, b, c, d, num if num == -1:
return False
fill(sudoku, a, b, c, d, num)return True
def solve(sudoku):
= 81 - (sudoku == 10).sum()
unknown while unknown != 0:
if not scan_and_fill(sudoku):
= np.unravel_index(sudoku.sum(axis=4).argmin(),
a, b, c, d =(3,3,3,3))
dims= np.nonzero(sudoku[a,b,c,d])[0]
num_list for num in num_list:
= sudoku.copy()
new_sudoku
fill(new_sudoku, a, b, c, d, num)if solve(new_sudoku):
= new_sudoku[:]
sudoku[:] return True
return False
-= 1
unknown return True
def read(quiz):
= np.ones((3, 3, 3, 3, 9), dtype=np.uint8)
sudoku for row in range(9):
for col in range(9):
= row // 3
a = row % 3
b = col // 3
c = col % 3
d = int(quiz[row][col])
num if num != 0:
-1)
fill(sudoku, a, b, c, d, numreturn sudoku
%%time
def problem96():
= 0
s for i in range(50):
= DATA.split()[11*i+2:11*i+11]
quiz = read(quiz)
sudoku
solve(sudoku)= np.nonzero(sudoku[0,0,0,:])[1]
a, b, c += (a+1)*100 + (b+1)*10 + (c+1)
s return s
print(problem96())
24702
CPU times: user 552 ms, sys: 0 ns, total: 552 ms
Wall time: 552 ms
Problem 97
%%time
def problem97():
28433*2**7830457+1
= (2**100000) % 10**10
two_to_100000 = (2**30457) % 10**10
two_to_30457 return (28433 * two_to_100000**78 * two_to_30457 + 1) % 10**10
print(problem97())
8739992577
CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 86.5 µs
Problem 98
from urllib.request import urlopen
from collections import defaultdict
= 'https://projecteuler.net/project/resources/p098_words.txt'
url with urlopen(url) as response:
= response.read().decode() DATA
%%time
def problem98():
= DATA.strip('"').split('","')
word_list = defaultdict(list)
anagram_dict for word in word_list:
''.join(sorted(word))].append(word)
anagram_dict[= dict((key, value)
filter_dict for (key, value) in anagram_dict.items() if len(value)>1)
= dict()
square_dict for i in set(len(key) for key in filter_dict.keys()):
= int((10**i-1)**0.5)
square_max = int((10**(i-1)-1)**0.5)+1
square_min = [x**2 for x in range(square_min, square_max+1)]
square_dict[i]
= 0
s_max for key in filter_dict:
if len(filter_dict[key]) == 2:
= filter_dict[key]
word1, word2 for square in square_dict[len(key)]:
= {w: s for w, s in zip(word1, str(square))}
match = {s: w for w, s in zip(word1, str(square))}
reverse_match if len(match) != len(key) or len(reverse_match) != len(key):
continue
= int(''.join([match[c] for c in word2]))
square2 if square2 in square_dict[len(key)]:
if square > s_max:
= square
s_max if square2 > s_max:
= square2
s_max return s_max
print(problem98())
18769
CPU times: user 116 ms, sys: 0 ns, total: 116 ms
Wall time: 115 ms
Problem 99
from urllib.request import urlopen
= 'https://projecteuler.net/project/resources/p099_base_exp.txt'
url with urlopen(url) as response:
= response.read().decode() DATA
%%time
def problem99():
= 1
x_max = 1
y_max = 0
line_max for line, pair in enumerate(DATA.split(), 1):
= [int(a) for a in pair.split(',')]
x, y if x > x_max**(y_max/y):
= x, y
x_max, y_max = line
line_max return line_max
print(problem99())
709
CPU times: user 4 ms, sys: 0 ns, total: 4 ms
Wall time: 1.05 ms
Problem 100
%%time
def problem100():
= (1, 1)
pell_fund = pell_fund
x, y while x <= 2*10**12-1:
= 3*x + 4*y, 2*x + 3*y
x, y return (y+1)//2
print(problem100())
756872327473
CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 122 µs