Question: import string import textwrap import re from collections import Counter from itertools import combinations import numpy as np english _ freq = { ' a
import string
import textwrap
import re
from collections import Counter
from itertools import combinations
import numpy as np
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 stringforcodeblockX linewidth:
return
jointextwrapwrapX widthlinewidth
def addspacesX width linewidth:
oneline jointextwrapwrapX widthwidth
manylines stringforcodeblockoneline, linewidthlinewidth
return manylines
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 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
def indcoX:
X onlylettersX case"upper"
ctr countsubstringsX
n sumctrvalues
return nnsumff for f in ctrvalues
def weavestringlist:
output joinjointup for tup in zipstringlist
# The rest is just to deal with the case of unequal string lengths
# We assume the only possibility is that the early strings are one character longer
lastlength lenstringlist
extra s for s in stringlist if lens lastlength
return output joinextra
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 case"lower":
Returns the proportion that each letter occurs in X
if case "lower":
letters string.asciilowercase
elif case "upper":
letters string.asciiuppercase
else:
raise ValueErrorcase should be 'upper' or 'lower'."
X onlylettersX casecase
n lenX
ctr countsubstringsX
output
for char in letters:
outputchar ctrcharn
return output
def kasiskidiffsY case"upper":
Y onlylettersY casecase
ctr countsubstringsY
trireps k for kv in ctritems if v
diffs
for tri in trireps:
starts mstart for m in refinditerftri Y
diffs.extendabsxy for xy in combinationsstarts
return nparraysorteddiffs
Encrypt a piece of English text using the above vigenere function with a random key of length or
You can generate a random key using the following, where keylength is your chosen length. The resulting key is a NumPy array rather than a list, but it should still work.
rng nprandom.defaultrng
key rngintegers sizekeylength
key
Your chosen text should be quite long, maybe characters. Just copy and paste from some source, and use triple quotation marks. Using triple quotation marks means that Python won't complain about line breaks or apostrophes or double quotation marks in your pasted text.
plaintext Your text here
Encrypt your chosen plaintext using the above key and the vigenere function. Store the resulting ciphertext using the variable name Y
Make the ciphertext less overwhelming to look at by evaluating the following.
printaddspacesY
Go to the "Lab Ciphertexts" thread on Canvas Discussion. Post the displayed ciphertext as a new response.
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
