You've been tasked with decrypting an enemy message intercepted by your team. You do not know the offset, but you do know a part of the original string, the variable word, that was there before the message was encrypted. Using that word and the encrypted string, decrypt the string, and then the original number used to offset it. There may be multiple possible combinations, so you will print all of them, and their offsets (no duplicates!)
Details :
The message will have UPPERCASE and lowercase letters, numbers and punctuation. You will convert all uppercase to lowercase, but keep all punctuation exactly where it was.
If a letter is offsetted to the edge of the alphabet, loop it around to the other side (for example, 'y' offsetted by +2 is 'a')
When printing the offset, you must give the most optimal offset (for example, and offset of 25 is -1, an offset of -28 is +2)
All non-letters (e.g '1', '?', 'space') will not be changed, and will remain in the original position.
The word will consist of only letters (though maybe uppercase) of length exceeding 1
If the message can not contain the word (for example, abc can never be cba), print 'impossible'
The answer should be in a list, with each answer then followed by their offset. The order is, from left to right, when the word can appear first.
Example: The string is 'abcefgh', the word is 'zab'. The first time zab can appear is ['zabdefg', 1], the second time it can appear is ['vwxzabc', -5,] and the third and last time it can appear is ['uvwyzab', -6], so your porgram should print ['zabdefg', -1, 'vwxzabc', -5, 'uvwyzab', -6].
You can import the alphabet under the variable name 'lc' by using (from string import ascii_lowercase as lc)
My solution doesn't work all the time, can anyone help me on why?
def decrypt(string, word) :
tempword = word.lower()
tempstring = string.lower()
from string import ascii_lowercase as lc
letters = {letter: str(index) for index, letter in enumerate(lc, start=1)}
def change(text) :
temp = []
for dex in range(len(text)) :
chan = text[dex]
try:
while chan > 13 or chan < -13 :
if chan < -13 :
chan = chan + 26
elif chan > 13 :
chan = chan - 26
temp.append(str(chan))
except:
temp.append(str(chan))
return '.'.join(temp)
def convert(text):
text = text.lower()
numbers = ['0', '0']
change = []
for character in text + text[-1] :
if character in letters :
numbers.append(letters[character])
if numbers[-2].isdigit() :
change.append(int(numbers[-1])-int(numbers[-2]))
else :
change.append(str(character))
return change[1:-1]
string = change(convert(string))
word = change(convert(word))
if string.count(word) == 0 :
return 'impossible'
answer = []
tempo = []
indexs = [i for i in range(len(string)) if string.startswith(word, i)]
for dex in range(sum(word == string[i:i+len(word)] for i in range(len(string)-(len(word)-1)))) :
nim = indexs[dex]+len(word)-1
location = string[:nim+1].count('.')
try :
if tempo.count(str(int(letters[tempstring[location]])-int(letters[tempword[0]]))) == 0 :
tempo.append(str(int(letters[tempstring[location]])-int(letters[tempword[0]])))
except :
True == True
tempo = change(tempo).split('.')
for dex in range(len(tempo)) :
offset = int(tempo[dex])
offset %= len(lc)
if (tempstring.translate(str.maketrans(lc, lc[-offset:] + lc[:-offset]))).count(tempword) != 0 :
answer.append(tempstring.translate(str.maketrans(lc, lc[-offset:] + lc[:-offset])))
return answer
def check(string, word) :
tempword = word.lower()
tempstring = string.lower()
from string import ascii_lowercase as lc
letters = {letter: str(index) for index, letter in enumerate(lc, start=1)}
def change(text) :
temp = []
for dex in range(len(text)) :
chan = text[dex]
try:
while chan > 13 or chan < -13 :
if chan < -13 :
chan = chan + 26
elif chan > 13 :
chan = chan - 26
temp.append(str(chan))
except:
temp.append(str(chan))
return '.'.join(temp)
def convert(text):
text = text.lower()
numbers = ['0', '0']
change = []
for character in text + text[-1] :
if character in letters :
numbers.append(letters[character])
if numbers[-2].isdigit() :
change.append(int(numbers[-1])-int(numbers[-2]))
else :
change.append(str(character))
return change[1:-1]
string = change(convert(string))
word = change(convert(word))
if string.count(word) == 0 :
return 'impossible'
answer = []
tempo = []
indexs = [i for i in range(len(string)) if string.startswith(word, i)]
for dex in range(sum(word == string[i:i+len(word)] for i in range(len(string)-(len(word)-1)))) :
nim = indexs[dex]+len(word)-1
location = string[:nim+1].count('.')
try :
if tempo.count(str(int(letters[tempstring[location]])-int(letters[tempword[0]]))) == 0 :
tempo.append(str(int(letters[tempstring[location]])-int(letters[tempword[0]])))
except :
True == True
tempo = change(tempo).split('.')
for dex in range(len(tempo)) :
offset = int(tempo[dex])
offset %= len(lc)
if (tempstring.translate(str.maketrans(lc, lc[-offset:] + lc[:-offset]))).count(tempword) != 0 :
answer.append(tempstring.translate(str.maketrans(lc, lc[-offset:] + lc[:-offset])))
return answer
Test.describe("Can you decrypt all these messages?")
Test.it("Random tests!")
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
non_letters = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '!', '@', '£', '$', '%', '^', '&', '*', '(', ')', ')', '!', '@', '£', '$', '%', '^', '&', '*', '(', ')', ')', ';Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
from random import shuffle
from random import randint
for index in range(100) :
shuffle(letters)
shuffle(non_letters)
rndlist = letters + non_letters
shuffle(rndlist)
rndstring = ''.join([str(i) for i in rndlist])
rndnum = randint(3, 10)
rndword = ''.join([str(i) for i in letters[0:rndnum]])
Test.assert_equals(decrypt(rndstring, rndword), check(rndstring, rndword))
Test.expect(decrypt(rndstring, rndword) == check(rndstring, rndword), 'Should work with random inputs too')