Fix problem number

This commit is contained in:
David Doblas Jiménez 2021-10-30 18:56:42 +02:00
parent a311ea75f8
commit 7190721c5f
10 changed files with 163 additions and 88 deletions

View File

@ -15,34 +15,45 @@ from utils import timeit, list_primes, is_prime
@timeit("Problem 51")
def compute():
"""
By replacing the 1st digit of the 2-digit number *3, it turns out that
By replacing the 1st digit of the 2-digit number *3, it turns out that
six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.
By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit
number is the first example having seven primes among the ten generated numbers,
yielding the family:
56003, 56113, 56333, 56443, 56663, 56773, and 56993.
Consequently 56003, being the first member of this family, is the smallest prime
By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit
number is the first example having seven primes among the ten generated numbers,
yielding the family:
56003, 56113, 56333, 56443, 56663, 56773, and 56993.
Consequently 56003, being the first member of this family, is the smallest prime
with this property.
Find the smallest prime which, by replacing part of the number (not necessarily
Find the smallest prime which, by replacing part of the number (not necessarily
adjacent digits) with the same digit, is part of an eight prime value family.
"""
primes = sorted(set(list_primes(1_000_000)) - set(list_primes(57_000)))
digits = {'0':[], '1':[], '2':[],'3':[], '4':[], '5':[],'6':[], '7':[], '8':[], '9':[]}
digits = {
"0": [],
"1": [],
"2": [],
"3": [],
"4": [],
"5": [],
"6": [],
"7": [],
"8": [],
"9": [],
}
for d in digits.keys():
for p in primes:
p = str(p)
if p.count(d) == 3 and p[-1] != d:
digits[d].append(p)
for d in {'0', '1', '2'}:
for d in {"0", "1", "2"}:
for p in digits[d]:
res = 0
i = 10
for D in {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}-{d}:
for D in {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} - {d}:
i -= 1
q = int(p.replace(d, D))
if is_prime(q) and q > 57_000:
@ -55,4 +66,4 @@ def compute():
if __name__ == "__main__":
print(f"Result for Problem {int(51):003d}: {compute()}")
print(f"Result for Problem 51: {compute()}")

View File

@ -15,22 +15,25 @@ from utils import timeit
@timeit("Problem 52")
def compute():
"""
It can be seen that the number, 125874, and its double, 251748,
It can be seen that the number, 125874, and its double, 251748,
contain exactly the same digits, but in a different order.
Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x,
Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x,
and 6x, contain the same digits.
"""
for number in range(123456, 1_000_000):
if sorted(str(number)) \
== sorted(str(2*number)) \
== sorted(str(3*number)) \
== sorted(str(4*number)) \
== sorted(str(5*number)) == sorted(str(6*number)):
if (
sorted(str(number))
== sorted(str(2 * number))
== sorted(str(3 * number))
== sorted(str(4 * number))
== sorted(str(5 * number))
== sorted(str(6 * number))
):
return number
if __name__ == "__main__":
print(f"Result for Problem {int(52):003d}: {compute()}")
print(f"Result for Problem 52: {compute()}")

View File

@ -27,7 +27,7 @@ def compute():
It is not until
, that a value exceeds one-million: (23 over 10) = 1144066.
How many, not necessarily distinct, values of (n over r) for 1<=n<=100, are greater than one-million?
How many, not necessarily distinct, values of (n over r) for 1<=n<=100, are greater than one-million?
"""
ans = 0
@ -41,4 +41,4 @@ def compute():
if __name__ == "__main__":
print(f"Result for Problem {int(53):003d}: {compute()}")
print(f"Result for Problem 53: {compute()}")

View File

@ -16,7 +16,7 @@ from utils import timeit
@timeit("Problem 54")
def compute():
"""
In the card game poker, a hand consists of five cards and are ranked,
In the card game poker, a hand consists of five cards and are ranked,
from lowest to highest, in the following way:
High Card: Highest value card.
@ -34,11 +34,11 @@ def compute():
2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
If two players have the same ranked hands then the rank made up of the
highest value wins; for example, a pair of eights beats a pair of fives
(see example 1 below). But if two ranks tie, for example, both players
have a pair of queens, then highest cards in each hand are compared
(see example 4 below); if the highest cards tie then the next highest
If two players have the same ranked hands then the rank made up of the
highest value wins; for example, a pair of eights beats a pair of fives
(see example 1 below). But if two ranks tie, for example, both players
have a pair of queens, then highest cards in each hand are compared
(see example 4 below); if the highest cards tie then the next highest
cards are compared, and so on.
Consider the following five hands dealt to two players:
@ -56,12 +56,12 @@ def compute():
5 2H 2D 4C 4D 4S 3C 3D 3S 9S 9D Player 1
Full House Full House
With Three Fours with Three Threes
The file, poker.txt, contains one-thousand random hands dealt to two
players. Each line of the file contains ten cards (separated by a single
space): the first five are Player 1's cards and the last five are Player
2's cards. You can assume that all hands are valid (no invalid characters
or repeated cards), each player's hand is in no specific order, and in
The file, poker.txt, contains one-thousand random hands dealt to two
players. Each line of the file contains ten cards (separated by a single
space): the first five are Player 1's cards and the last five are Player
2's cards. You can assume that all hands are valid (no invalid characters
or repeated cards), each player's hand is in no specific order, and in
each hand there is a clear winner.
How many hands does Player 1 win?
@ -79,7 +79,6 @@ def compute():
def to_numerical(hand: list) -> list:
return sorted([int(x[:-1]) for x in hand], reverse=True)
# 10 Ranks functions.
def high_card(str_hand: list) -> list:
return to_numerical(str_hand)
@ -87,7 +86,7 @@ def compute():
def one_pair(hand: list) -> int:
return n_of_a_kind(hand, 2)
def two_pair(hand: list) -> int:
def two_pair(hand: list) -> int:
pairs = set([x for x in hand if hand.count(x) == 2])
return 0 if len(pairs) < 2 else max(pairs)
@ -95,7 +94,7 @@ def compute():
return n_of_a_kind(hand, 3)
def straight(hand: list) -> int:
return 0 if not list(range(hand[0], hand[-1]-1, -1)) == hand else max(hand)
return 0 if not list(range(hand[0], hand[-1] - 1, -1)) == hand else max(hand)
def flush(str_hand: list) -> bool:
return len(set([x[-1] for x in str_hand])) == 1
@ -113,7 +112,6 @@ def compute():
def royal_flush(str_hand: list) -> bool:
return flush(str_hand) and list(range(14, 9, -1)) == to_numerical(str_hand)
replace_map = {"T": 10, "J": 11, "Q": 12, "K": 13, "A": 14}
score = [0, 0]
@ -121,10 +119,25 @@ def compute():
for line in open(file, "r").read().splitlines():
line = replace_values_in_string(line, replace_map).split()
hands = line[:5], line[5:]
for rank in (royal_flush, straight_flush, four_of_a_kind, full_house, flush,
straight, three_of_a_kind, two_pair, one_pair, high_card):
should_convert_hand = "str" not in rank.__code__.co_varnames[0] # Checks parameter name.
result = [rank(to_numerical(hand) if should_convert_hand else hand) for hand in hands]
for rank in (
royal_flush,
straight_flush,
four_of_a_kind,
full_house,
flush,
straight,
three_of_a_kind,
two_pair,
one_pair,
high_card,
):
should_convert_hand = (
"str" not in rank.__code__.co_varnames[0]
) # Checks parameter name.
result = [
rank(to_numerical(hand) if should_convert_hand else hand)
for hand in hands
]
if result[0] != result[1]:
score[0 if result[0] > result[1] else 1] += 1
break
@ -134,4 +147,4 @@ def compute():
if __name__ == "__main__":
print(f"Result for Problem {int(54):003d}: {compute()}")
print(f"Result for Problem 54: {compute()}")

View File

@ -31,13 +31,13 @@ def compute():
of these numbers, and for the purpose of this problem, we shall assume that a
number is Lychrel until proven otherwise. In addition you are given that for
every number below ten-thousand, it will either:
(i) become a palindrome in less than fifty iterations, or,
(i) become a palindrome in less than fifty iterations, or,
(ii) no one, with all the computing power that exists, has managed so far to map
it to a palindrome.
In fact, 10677 is the first number to be shown to require over fifty iterations
before producing a palindrome:
4668731596684224866951378664 (53 iterations, 28-digits).
Surprisingly, there are palindromic numbers that are themselves Lychrel numbers;
@ -57,10 +57,10 @@ def compute():
break
if is_lychrel:
ans += 1
return ans
if __name__ == "__main__":
print(f"Result for Problem {int(55):003d}: {compute()}")
print(f"Result for Problem 55: {compute()}")

View File

@ -15,7 +15,7 @@ from utils import timeit
@timeit("Problem 56")
def compute():
"""
A googol (10^100) is a massive number: one followed by one-hundred zeros;
A googol (10^100) is a massive number: one followed by one-hundred zeros;
100100 is almost unimaginably large: one followed by two-hundred zeros.
Despite their size, the sum of the digits in each number is only 1.
@ -26,7 +26,7 @@ def compute():
ans = 0
for a in range(100):
for b in range(100):
num = sum([int(digit) for digit in str(a**b)])
num = sum([int(digit) for digit in str(a ** b)])
if num > ans:
ans = num
@ -35,4 +35,4 @@ def compute():
if __name__ == "__main__":
print(f"Result for Problem {int(56):003d}: {compute()}")
print(f"Result for Problem 56: {compute()}")

View File

@ -16,7 +16,7 @@ from utils import timeit
@timeit("Problem 57")
def compute():
"""
It is possible to show that the square root of two can be expressed
It is possible to show that the square root of two can be expressed
as an infinite continued fraction.
By expanding this for the first four iterations, we get:
@ -26,11 +26,11 @@ def compute():
1 + 1/2+1/2+1/2 = 17/12 = 1.41666...
1 + 1/2+1/2+1/2+1/2 = 41/29 = 1.41379...
The next three expansions are 99/70, 239/169, and 577/408, but the eighth
expansion, 1393/985, is the first example where the number of digits in
The next three expansions are 99/70, 239/169, and 577/408, but the eighth
expansion, 1393/985, is the first example where the number of digits in
the numerator exceeds the number of digits in the denominator.
In the first one-thousand expansions, how many fractions contain a numerator
In the first one-thousand expansions, how many fractions contain a numerator
with more digits than the denominator?
"""
@ -41,10 +41,10 @@ def compute():
result = 1 + f
if len(str(result.numerator)) > len(str(result.denominator)):
ans += 1
return ans
if __name__ == "__main__":
print(f"Result for Problem {int(57):003d}: {compute()}")
print(f"Result for Problem 57: {compute()}")

View File

@ -15,7 +15,7 @@ from utils import timeit, is_prime
@timeit("Problem 58")
def compute():
"""
Starting with 1 and spiralling anticlockwise in the following way,
Starting with 1 and spiralling anticlockwise in the following way,
a square spiral with side length 7 is formed.
37 36 35 34 33 32 31
@ -26,13 +26,13 @@ def compute():
42 21 22 23 24 25 26
43 44 45 46 47 48 49
It is interesting to note that the odd squares lie along the bottom right
diagonal, but what is more interesting is that 8 out of the 13 numbers
It is interesting to note that the odd squares lie along the bottom right
diagonal, but what is more interesting is that 8 out of the 13 numbers
lying along both diagonals are prime; that is, a ratio of 8/13 62%.
If one complete new layer is wrapped around the spiral above, a square
spiral with side length 9 will be formed. If this process is continued,
what is the side length of the square spiral for which the ratio of primes
If one complete new layer is wrapped around the spiral above, a square
spiral with side length 9 will be formed. If this process is continued,
what is the side length of the square spiral for which the ratio of primes
along both diagonals first falls below 10%?
"""
@ -53,4 +53,4 @@ def compute():
if __name__ == "__main__":
print(f"Result for Problem {int(58):003d}: {compute()}")
print(f"Result for Problem 58: {compute()}")

View File

@ -17,37 +17,37 @@ from utils import timeit
@timeit("Problem 59")
def compute():
"""
Each character on a computer is assigned a unique code and the preferred
standard is ASCII (American Standard Code for Information Interchange).
Each character on a computer is assigned a unique code and the preferred
standard is ASCII (American Standard Code for Information Interchange).
For example, uppercase A = 65, asterisk (*) = 42, and lowercase k = 107.
A modern encryption method is to take a text file, convert the bytes to
ASCII, then XOR each byte with a given value, taken from a secret key.
The advantage with the XOR function is that using the same encryption key
on the cipher text, restores the plain text; for example, 65 XOR 42 = 107,
A modern encryption method is to take a text file, convert the bytes to
ASCII, then XOR each byte with a given value, taken from a secret key.
The advantage with the XOR function is that using the same encryption key
on the cipher text, restores the plain text; for example, 65 XOR 42 = 107,
then 107 XOR 42 = 65.
For unbreakable encryption, the key is the same length as the plain text
message, and the key is made up of random bytes. The user would keep the
encrypted message and the encryption key in different locations, and
For unbreakable encryption, the key is the same length as the plain text
message, and the key is made up of random bytes. The user would keep the
encrypted message and the encryption key in different locations, and
without both "halves", it is impossible to decrypt the message.
Unfortunately, this method is impractical for most users, so the modified
method is to use a password as a key. If the password is shorter than the
message, which is likely, the key is repeated cyclically throughout the
message. The balance for this method is using a sufficiently long password
Unfortunately, this method is impractical for most users, so the modified
method is to use a password as a key. If the password is shorter than the
message, which is likely, the key is repeated cyclically throughout the
message. The balance for this method is using a sufficiently long password
key for security, but short enough to be memorable.
Your task has been made easy, as the encryption key consists of three
lower case characters. Using p059_cipher.txt, a file containing the
encrypted ASCII codes, and the knowledge that the plain text must contain
common English words, decrypt the message and find the sum of the ASCII
Your task has been made easy, as the encryption key consists of three
lower case characters. Using p059_cipher.txt, a file containing the
encrypted ASCII codes, and the knowledge that the plain text must contain
common English words, decrypt the message and find the sum of the ASCII
values in the original text.
"""
with open('../files/Problem59.txt', 'r') as f:
with open("../files/Problem59.txt", "r") as f:
# encrypted = list(map(int, f.read().split(',')))
encrypted = [int(char) for char in f.read().split(',')]
encrypted = [int(char) for char in f.read().split(",")]
# print(encrypted)
# print(test)
plain_text = len(encrypted) // 3
@ -55,12 +55,12 @@ def compute():
decrypted = ""
for k, i in zip(list(key) * plain_text, encrypted):
decrypted += chr(ord(k) ^ i)
# assuming Euler will be in the text
if 'Euler' in decrypted:
if "Euler" in decrypted:
return sum([ord(c) for c in decrypted])
if __name__ == "__main__":
print(f"Result for Problem {int(59):003d}: {compute()}")
print(f"Result for Problem 59: {compute()}")

View File

@ -0,0 +1,48 @@
import math
from functools import wraps
def timeit(name):
def profile(original):
import time
@wraps(original)
def wrapper(*args, **kwargs):
t0 = time.perf_counter()
result = original(*args, **kwargs)
t1 = time.perf_counter()
print(f"Time to evaluate problem {int(name[7:]):003d}: {(t1 - t0)*1000:.3f} ms\n")
return result
return wrapper
return profile
def is_prime(n):
if n <2:
return False
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
# Returns a list of True and False indicating whether each number is prime.
# For 0 <= i <= n, result[i] is True if i is a prime number, False otherwise.
def list_primality(n):
# Sieve of Eratosthenes
result = [True] * (n + 1)
result[0] = result[1] = False
for i in range(int(math.sqrt(n) + 1)):
if result[i]:
for j in range(i * i, len(result), i):
result[j] = False
return result
# Returns all the prime numbers less than or equal to n, in ascending order
# For example: list_primes(97) = [2, 3, 5, 7, 11, ..., 83, 89, 97].
def list_primes(n):
return [i for (i, is_prime) in enumerate(list_primality(n)) if is_prime]
def is_palindrome(num):
return str(num) == str(num)[::-1]