Question: import string from collections import Counter # Computed from A Tale of Two Cities. Compare Table 1 . 3 in Hoffstein, Pipher, Silverman. english _
import string
from collections import Counter
# Computed from "A Tale of Two Cities". Compare Table in Hoffstein, Pipher, Silverman.
englishfreq
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:
def onlylettersX caseNone:
Returns the string obtained from X by removing everything but the letters.
If case"upper" or case"lower", then the letters are all
converted to the same case.
X joinc for c in X if c in string.asciiletters
if lenX:
return None
if case is None:
return X
elif case "lower":
return Xlower
elif case "upper":
return Xupper
def shiftcharch shiftamt:
Shifts a specific character by shiftamt.
Example:
shiftcharY returns B
if ch in string.asciilowercase:
base a
elif ch in string.asciiuppercase:
base A
# It's not clear what shifting should mean in other cases
# so if the character is not upper or lowercase, we leave it unchanged
else:
return ch
return chrordchordbaseshiftamtordbase
def shiftstringX shiftamt:
Shifts all characters in X by the same amount.
return joinshiftcharch shiftamt for ch in X
def countsubstringsXn:
Returns a Python Counter object of all ngrams in X
if not X:
return
X onlylettersX
shifts Xi: for i in rangen
grams joinchrs for chrs in zipshifts
return Countergrams
def getfreqX:
Returns the proportion that each letter occurs in X
I might change this later, but for now, it converts everything to lowercase.
The reason is to match what appears in the englishfreq dictionary.
X onlylettersX case"lower"
n lenX
ctr countsubstringsX
output
for char in string.asciilowercase:
outputchar ctrcharn
return output
def mutindcod d:
For letter frequency dictionaries d and d return the Mutual Index of Coincidence.
See Equation on page in Hoffstein, Pipher, Silverman.
s
for k in dkeys:
s dgetkdgetk
return s
import numpy as np
def naivedecryptY:
holder npzeros
for i in range:
X shiftstringY i
holderi XcountE
# npargmax finds the location of the maximum value.
# If the maximum is obtained multiple times, only the first index is returned.
shiftamt npargmaxholder
X shiftstringY shiftamt
return X shiftamt
def shiftdecryptY:
Automatically decrypt ciphertext that has been encrypted using a shift cipher.
This function returns the decrypted string and the shift amount.
maxic
bestshift
bestdecryption
for i in range:
decryptedtext shiftstringY i
freqdict getfreqdecryptedtext
ic mutindcofreqdict, englishfreq
if ic maxic:
maxic ic
bestshift i
bestdecryption decryptedtext
return bestdecryption, bestshift
Encrypt the string INTROCRYPTOGRAPHY using a shift cipher. Use the shiftstring function... don't do this by hand. Store the resulting ciphertext using the variable name Y
Evaluate Ytheres no need to use print just execute a code cell with Y in it to see what the encrypted text looks like.
Does your shiftdecrypt function find the true plaintext in this case?
Notice that the returned shift amount is different from the shift amount you used for encryption unless you chose a shift amount of or Briefly explain why that's the case in a markdown cell.
Notice that a different shift amount being returned is not an indication of a mistake in our code.
Try evaluating naivedecrypt on the ciphertext you made. Youll first need to execute the naivedecrypt code by pasting it into a code cell and then evaluating that cell.
How could we have known in advance that the naive strategy would not work in this case? Briefly explain in a markdown cell.
Find an example of text for which your shiftdecrypt function does not work. Try to make the original English text at least a few words.
Step by Step Solution
There are 3 Steps involved in it
1 Expert Approved Answer
Step: 1 Unlock
Question Has Been Solved by an Expert!
Get step-by-step solutions from verified subject matter experts
Step: 2 Unlock
Step: 3 Unlock
