67 lines
2.5 KiB
Python
67 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Created on 13 Oct 2021
|
|
|
|
@author: David Doblas Jiménez
|
|
@email: daviddoji@pm.me
|
|
|
|
Solution for problem 59 of Project Euler
|
|
https://projecteuler.net/problem=59
|
|
"""
|
|
|
|
from itertools import permutations
|
|
from string import ascii_lowercase
|
|
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).
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
values in the original text.
|
|
"""
|
|
|
|
with open("../files/Problem59.txt", "r") as f:
|
|
# encrypted = list(map(int, f.read().split(',')))
|
|
encrypted = [int(char) for char in f.read().split(",")]
|
|
# print(encrypted)
|
|
# print(test)
|
|
plain_text = len(encrypted) // 3
|
|
for key in permutations(ascii_lowercase, 3):
|
|
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:
|
|
return sum([ord(c) for c in decrypted])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
print(f"Result for Problem 59: {compute()}")
|