alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# Multiplication cipher
def mult_cipher(plaintext, key):
"""Convert each char c to number n using alpha.
Then n-> n*key mod 26. Convert back to char"""
ciphertext = []
for i in range(len(plaintext)):
c = plaintext[i]
numc = alpha.find(c)
multnumc = (numc * key) % 26 # only significant change vs shift_cipher
codedc = alpha[multnumc]
ciphertext.append(codedc)
return ciphertext
"".join(mult_cipher("ABCDEFGHIJKLMNOPQRSTUV", 3))
"".join(mult_cipher("ABCDEFGHIJKLMNOPQRSTUV", 2))
mult_cipher('A',2)
mult_cipher('N',2)
# From the encrypted message 'A', can't tell whether original message was
# 'A' or 'N'
# So 2 is not a good encryption key to use
# To decipher mult_cipher(plaintext, 3), use mult_cipher(ciphertext, 9)
# Works because 3*9 % 26 = 1
"".join(mult_cipher('ADGJMPSVYBEHKNQTWZCFIL', 9))
mult_cipher("HELLO", 3)
# Want to understand whick keys can be inverted modulo 26
# Need to understand when two numbers a,b have a common factor
# For this, we will use the technique of recursion to compute gcd (next time)
# Intro to recursino
# factorial function n!, WITHOUT recursion, using loop
def fact_loop(n):
run_prod = 1
for i in range(1,n+1):
run_prod *= i
return run_prod
fact_loop(5)
# factorial WITH recursion
def fact(n):
print(n)
if n==1:
return 1 # base case
else:
return n * fact(n-1) # function calls itself here: a recursive call
fact(3)
# CHALLENGE: compute nth elt of fibonacci sequence using recursion
# a0=1, a1=1, a2=2, a3=3, a4=5, a5=8, a6=13
def fib(n):
if n==0 or n==1:
return 1
return fib(n-1) + fib(n-2)
[fib(n) for n in range(10)] # test above
fib(20)
# this fib function is slower than the fib function from a previous class
# Reason: there is a slot of redunancy
# (for instance, computes fib(n-2) multiple times)