Strings and Random Numbers
Caesar and Vigenère CiphersJohn K. Bennett
IWKS 2300Fall 2019
String Special CharactersSpecial characters can be inserted in a string using an escape
sequence, which is a backslash (\) followed by another character.
Here are some common escape sequences:
\" Double Quote \\ Backslash
\n Newline \t Horizontal Tab
print("Favorite Color:\n\t\"Glow in the Dark\"")
Favorite Color:
"Glow in the Dark"
Single or Double Quotes: Your Choice
Strings can be written using either single or double quotes, your choice.
primary = 'Python'
secondary = "English"
Using single quotes means no need to escape double quotes:
Using double quotes means no need to escape single quotes:
print('So you must be "the one"?')
print("Margaret's house is blue.")
Strings Are Like Lists (almost)
Strings are like lists containing characters:
my_name = "Jack"
print(my_name[0])
J
my_name = "Jack"
my_name[0] = "T" # produces item assignment error
But unlike lists, strings cannot be modified
Strings Are Iterables
You can iterate over each character of a string.
for char in "IWKS 2300"
print(char)
I
W
K
S
2
3
0
0
Spliting strings with .split()To separate the words in a string into a list, call .split() on the string.
my_str = "Python is really cool"
word_list = my_str.split()
# wordlist will be ["Python", "is", ... ]
for word in word_list:
print(word)
Python
is
really
cool
Note: The dot (".") above is called the accessor operator (though most programmers simply call it the dot operator). This syntax allows us to use a function that is specific to a certain data type on the object.
Using .split()
The input() function returns a string containing the line that the user typed. Often you need to split that input, e.g.:
line = input("What is your full name?")
words = line.split()
firstname = words[0]
lastname = words[1]
Joining Strings With .join().join() does the opposite of .split(). It also allows you to specify
what you want to use as a separator.
separator = "@"
word_list = ["jkb", "ucdenver.edu"]
email = separator.join(wordlist)
print(email)
String Formatting - Old StyleThree basic formatting specifiers (C-Style) are:● %s - String● %d - Integers● %f - Floatsname = 'John'
i_age = 21
f_age = 21.5
print('Hello, %s. Are you %d or %f?' %(name, i_age, f_age))
print()
print("We can print %f or %.2f. How?" %(f_age, f_age))
Hello, John. Are you 21 or 21.500000?
We can print 21.500000 or 21.50. How?
String Formatting - New StyleThe "new style" string formatting gets rid of the %-operatorsyntax, and instead calls the .format() function on a string object.
name = 'John'
i_age = 21
f_age = 21.5
print('Hello, {}. Are you {} or {}?'.format(name, i_age, f_age))
print()
print('Hello, {name}. You are {age}.'.format(name=name, age=i_age))
Hello, John. Are you 21 or 21.5?
Hello, John. You are 21.
New New String Formatting: f-strings
Python 3.6+ offers a new formatting string approach: "f-strings". This new way of formatting strings lets you use embedded Python expressions inside string constants.
name = 'John'
i_age = 21
f_age = 21.5
print(f"Hello, {name}. Aren't you really {i_age - 3}?")
Hello, John. Aren't you really 18?
ASCII Character Representation
Character Manipulation in Python
The Python function ord() returns the ordinal ASCII number of a character, e.g.,
print(ord('A'))results in:65
Similarly, the Python function chr() is the inverse of ord(), e.g., print(chr(122))
results in:z
Character Manipulation in Python
The Python character methods isupper()and islower() return Trueif the character is uppercase or lower case, respectively.Running this code:
lchar = 'a'
uchar = 'G'
if lchar.islower():
print (lchar + ' is a lowercase letter')
if uchar.isupper():
print (uchar + ' is an uppercase letter')
will produce the following output:a is a lowercase letterG is an uppercase letter
How to Generate a Random Number
Import the Random Library:import random
To create a random integer that ranges from [a, b]random.randint(a, b)
To create a random float that ranges from [0, 1)random.random() # no parameters, includes 0, excludes 1!
How to generate a random integer that ranges from 1 to 10?
How to generate a random integer that ranges from 0 to 7?
>>> random.randint(1, 10)
>>> random.randint(0, 7)
How to generate a random float that ranges from 0 to 5?
>>> random.random() * 5 # number from [0, 5)
How to generate a random float that ranges from 1 to 6?
>>> random.random() * 5 + 1 # number from [1, 6)
Example of Generating Random Numbers
Practice: How Do You…
• Generate a random integer that ranges from [5, 8]:
• Generate a random float that ranges from [0, 2.5]:
• Generate a random float that ranges from [3, 7]:
• Generate a random float that ranges from [3, 7.5]:
• Generate a random float that ranges from [2.5 to 3.75]:
Practice: How Do You…
• Generate a random integer that ranges from [5, 8]:
• Generate a random float that ranges from [0, 2.5]:
• Generate a random float that ranges from [3, 7]:
• Generate a random float that ranges from [3, 7.5]:
• Generate a random float that ranges from [2.5 to 3.75]:
random.randint(5, 8)
Practice: How Do You…• Generate a random integer that ranges from [5, 8]:
• Generate a random float that ranges from [0, 2.5]:
• Generate a random float that ranges from [3, 7]:
• Generate a random float that ranges from [3, 7.5]:
• Generate a random float that ranges from [2.5 to 3.75]:
random.randint(5, 8)
random.random() * 2.5
Practice: How Do You…• Generate a random integer that ranges from [5, 8]:
• Generate a random float that ranges from [0, 2.5]:
• Generate a random float that ranges from [3, 7]:
• Generate a random float that ranges from [3, 7.5]:
• Generate a random float that ranges from [2.5 to 3.75]:
random.randint(5, 8)
random.random() * 2.5
random.random() * 4 + 3
Practice: How Do You…• Generate a random integer that ranges from [5, 8]:
• Generate a random float that ranges from [0, 2.5]:
• Generate a random float that ranges from [3, 7]:
• Generate a random float that ranges from [3, 7.5]:
• Generate a random float that ranges from [2.5 to 3.75]:
random.randint(5, 8)
random.random() * 2.5
random.random() * 4 + 3
random.random() * 4.5 + 3
Practice: How Do You…• Generate a random integer that ranges from [5, 8]:
• Generate a random float that ranges from [0, 2.5]:
• Generate a random float that ranges from [3, 7]:
• Generate a random float that ranges from [3, 7.5]:
• Generate a random float that ranges from [2.5 to 3.75]:
random.randint(5, 8)
random.random() * 2.5
random.random() * 4 + 3
random.random() * 4.5 + 3
random.random() * 1.25 + 2.5
Each letter in the plaintext message is replaced by a letter some
fixed number of positions from that letter in the alphabet. For
example, with a left shift of three (the "key" purportedly used by
Caesar), D would be replaced by G, E would become H, e.g.:Plaintext Alphabet: Cipher Alphabet:
Caesar Cipher
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
X Y Z G H I J K L M N O P Q R S T U V W X Y Z A B C
To encrypt a message, we replace each plain alphabet letter
of the plaintext message with the cipher alphabet letter
corresponding to the plain letter. Example:
Plaintext: WE WILL ATTACK AT DAWN UNLESS ITS RAINING
Ciphertext: ZH ZLOO DWWDFN DW GDZQ XQOHVV LWV UDLQLQJ
To decrypt the message, we apply the opposite shift.
Caesar Cipher Encryption
The "Vigenère Cipher" improves upon the Caesar cipher by
applying it differently for each letter, using the letters of a
"keyword" to determine the specific Caesar shift to use for each
letter. The Vigenère cipher is named for Blaise de Vigenère, who
wrote of it, but the cipher was actually invented by Giovan
Battista Bellaso in 1553, who was building upon the work of
others, most notably, Johannes Trithemius, who created the
tabula recta, on which the Vigenère cipher is based.
The tabula recta is just a table of all possible Caesar ciphers.
The Vigenère Cipher chooses a particular Caesar cipher for
each letter based upon a Key.
Vigenère Cipher
Tabula Recta
A Vigenère cipher will use
only as many Caesar
cipher keys in the Tabula
Recta as there are unique
letters in the Key. If the
message is longer than the
Key, the letters of the Key
will be reused in the same
order
Plaintext: WE WILL ATTACK AT DAWN UNLESS ITS RAINING
KEY: COMPUTERSCIENCEISAWESOME
Ciphertext: YS IXFE EKLCKO NV HION QRDSEW KHE GUBRZFI
Vigenère Cipher Example If the first letter of the plaintext message is W, and the first letter
of the Key is C, row C and column W of the Tabula Recta yields
a Y. So, to encrypt a message, we replace each plain alphabet
letter of the Plaintext message with the Ciphertext letter found
in the tabula recta at the location determined by the Key.
Vigenère Cipher Implementation"Write a Python program that implements the Vigenère
cipher, allowing the user to specify the plaintext and the key
(for encryption), or the ciphertext and the key (for decryption
Make sure you handle both upper case and lower case
letters, but numbers and other characters (like spaces)
should be passed through unmodified." Keys can only
contain letters.
Hint 1: You do not have to build a tabula recta table to do
the encryption/decryption.
Hint 2: Get the Caesar cipher working first, then extend it to
Vigenère.
Vigenère Cipher Implementation
1. For each letter in the plaintext, extract the corresponding
letter from the key (wrapping the key as necessary).
2. Use the ordinal number of the key letter (minus the
ordinal number of ‘A’ or ‘a’, as appropriate), as the
keyshift for that plaintext character.
3. Then just apply the Caesar cipher for the plaintext letter
with that keyshift.
4. Repeat for each letter in the plaintext message.