Question: def kasiski _ diffs ( Y , case = upper ) : Y = only _ letters ( Y , case = case ) ctr

def kasiski_diffs(Y, case="upper"):
Y = only_letters(Y, case=case)
ctr = count_substrings(Y,3)
tri_reps =[k for k,v in ctr.items() if v >1]
diffs =[]
for tri in tri_reps:
starts =[m.start() for m in re.finditer(f'(?={tri})', Y)]
diffs.extend([abs(x-y) for x,y in combinations(starts,2)])
return np.array(sorted(diffs))
def ind_co(X):
X = only_letters(X, case="upper")
ctr = count_substrings(X,1)
n = sum(ctr.values())
return (1/(n*(n-1)))*sum(f*(f-1) for f in ctr.values())
* In lecture on D20240701, we used (an estimate for) the Index of Coincidence to distinguish random characters from shift ciphertext. One strength of the Vigenre cipher is that it looks very much like random text from this perspective. Compute `ind_co(Y)` for `Y` as above, and compare it with `1/26`, which is the value expected for randomly chosen English characters. (**Comment**. We've changed `ind_co` since Monday. It used to take a dictionary of letter frequencies as input, like `mut_ind_co`. Now it takes a string as input.)
* On the other hand, the above was encrypted using a Vigenre cipher with a key length of `7`. Compute the following and compare the values with the expected Index of Coincidence value for true English of approximately `0.068`.(All of the values will be close to, but slightly less than, this `0.068` value. I'm not sure if there is a theoretical reason for why they are less than `0.068`. The important thing is they're all significantly closer to the true English value than to the random characters value.)
```
Z = only_letters(Y) # we remove spaces from `Y`
for i in range(7):
print(ind_co(Z[i::7]))
```
* Write a function to perform Vigenre encryption using the following template. (If you want to make the code more elegant, replace `for i in range(key_length):` in our template with `for i, k in enumerate(key):`.)
> Input: a string `X` and a list of shift amounts `key`
> Output: a string `Y`
>
> Example: If `X` is `"The rain in Spain stays mainly in the plain"` and `key` is `[5,11,0,12,8,13,6,14]`, then the output should be the ciphertext written on page 217 of our textbook, beginning `"YSEDIVTWSDPM..."`.
```
def vigenere(X, key, case="upper"):
X = only_letters(X, case=case)
key_length = len(key)
string_list =[]
for i in range(key_length):
s = # Get the characters in `X` at integer positions ??? modulo ???
shifted_s = # Shift the characters in s. Use the imported `shift_string` function.
string_list.append(shifted_s)
output = # Use the imported `weave` function
return output
```* Test your function by evaluating the following and checking that the result matches what is on page 217 of the textbook (aside from ours being in upper-case letters).
```
X = "The rain in Spain stays mainly in the plain"
key =[5,11,0,12,8,13,6,14]
vigenere(X, key)
```

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!