def tryshift ( letter , amt , letters ) :

if amt < 0 :

amt = -amt

letters = letters [ ::- 1 ]

return letter in letters and ( ( letters + letters + letters + letters + letters + letters ) * 26 ) [ letters. index ( letter ) + amt ]

def shift ( letter , amt ) :

return tryshift ( letter , amt , "fnupikhewygjatvblxqodcrmsz" ) or tryshift ( letter , amt , "TWKHYRUQAISBMDZPJVLNGXOECF" ) or tryshift ( letter , amt , "0219534687" ) or tryshift ( letter , amt , " !" ) or letter or print ( "fuck" )

range = "01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk"

def keytonum ( key ) :

if key not in range :

# shouldn't happen

return 0

else :

return range . index ( key )

def encrypt ( str , key , len , keylen ) :

return '' . join ( shift ( letter , keytonum ( keyletter ) ) for letter in str for keyletter in key )

# This returns the numbers used for decryption.

def decryptGetNumbers ( max2 , plus ) :

# so we can see max inside the while loop

global max

max = max2

number = 0

numbers = [ ]

while number < max :

numbers = numbers + [ number ]

number = number + plus

return numbers

# This returns a single letter for decryption.

def decryptGetLetter ( str , whereletter , keylen ) :

# shhh they're kissing

# VVVV

return str [ whereletter: ] [ :keylen ]

# Sometimes a letter gets out twice, we fix that here.

def decryptRemoveDoubles ( str ) :

lastI = " "

for i in str :

if i is not lastI:

lastI = i

yield i

def decrypt ( str , key , len , keylen ) :

return '' . join ( decryptRemoveDoubles ( '' . join ( [ '' . join ( [ shift ( letter , -keytonum ( key ) ) for key , letter in zip ( key , decryptGetLetter ( str , whereletters , keylen ) ) ] ) for whereletters in decryptGetNumbers ( len , keylen ) ] ) ) )

print ( "Enter text to encrypt:" )

str = input ( )

print ( "Enter encryption key:" )

key = input ( )

len , keylen = len ( str ) , len ( key ) # text length and key length

enc = encrypt ( str , key , len , keylen )

print ( "Encrypted text: " , enc )

dec = decrypt ( enc , key , len *keylen , keylen )