# Caesar Cipher in Python

## What is a Caesar cipher?

A Caesar cipher is an example of a substitution cipher. Essentially, you take the starting phrase and shift each letter of the word or phrase a certain number of spots down the alphabet. Traditionally, Caesar used a shift of 3, but you can also use other numbers.

![Caesar Cipher by Wikipedia Commons](https://upload.wikimedia.org/wikipedia/commons/7/75/Caesar_substition_cipher.png)

In other words, if I use a shift of 5, the word "hello" should return as "mjqqt". With a shift of 2, it will be "ifmmp"

You can read more about it on the [Wikipedia page](https://en.wikipedia.org/wiki/Caesar_cipher) or the [Simplified Wikipedia page](https://simple.wikipedia.org/wiki/Caesar_cipher).

## Requirements

In order to create a Caesar cipher tool, it will be useful to know the following functions and concepts. Click on each concept to learn more about it.

* [Variables](https://www.w3schools.com/python/python_variables.asp)
* [Modulo](https://www.w3schools.com/python/python_operators.asp)
* [For loops](https://www.w3schools.com/python/python_for_loops.asp)
* [If statements](https://www.w3schools.com/python/python_conditions.asp)
* [functions](https://www.w3schools.com/python/python_functions.asp)
* [chr()](https://www.w3schools.com/python/ref_func_chr.asp)
* [ord()](https://www.w3schools.com/python/ref_func_ord.asp)
* [isalpha()](https://www.w3schools.com/python/ref_string_isalpha.asp)
* [isupper()](https://www.w3schools.com/python/ref_string_isupper.asp)
* [islower()](https://www.w3schools.com/python/ref_string_islower.asp)
* [What ASCII is](https://www.computerhope.com/jargon/a/ascii.htm)

It will also help to have an ASCII table ready, such as [this one](https://www.ascii-code.com/).

![ASCII Table by Wikipedia Commons](https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/ASCII-Table-wide.svg/640px-ASCII-Table-wide.svg.png)

## Explanation

The core component of the Caesar cipher is the following formula:

```python
for character in phrase:
    chr((ord(character) + shift - i) % 26 + i)
```

In the above example, `i` is 65 for uppercase letters and 97 for lowercase letters. That is because the ASCII code for the first letter of the alphabet, A, is 65 for uppercase and 97 for lowercase. The `shift` variable is how many spaces we want to shift our starting phrase by.

{% hint style="info" %}
Remember that `character`, `shift`, `phrase` and `i` are just variable names. You can name your variables whatever you want. For example, instead of`character`, you can call it `letter`, or even something else. Just try to use names that make sense and describe the use of the variable.
{% endhint %}

The `chr()` function takes a number and returns the equivalent character according to the ASCII table. For example, `chr(70)` will return an uppercase F.

The `ord()` function returns the ASCII number of a character. So `ord('B')` will return 66.

<details>

<summary>Practice. Use an ASCII table to find the ASCII codes for the phrase "I like Python".</summary>

The correct answer is: 73 32 108 105 107 101 32 80 121 116 104 111 110. Note how even the space has it's own ASCII code (32), and that capital letters have different codes than lower case ones.

</details>

### How does it work?

Let's assume that we will work with uppercase letters.

First, there is this part:

```python
ord(character)
```

Since we are running this function in a loop (remember, it's the `for character in phrase` part), it will get the `ord()`, or the ASCII code, of each character in that phrase. We will then end up with a sequence of numbers. So if I input the phrase "SAREL", I will get the numbers 83, 65, 82, 69 and 76. By changing these numbers and converting them back into characters, we can get different characters than what we started with! And that is exactly what we will do.

```python
ord(character) + shift
```

Here, we add the `shift` amount to our ASCII numbers. In other words, if we use a shift of 3, then 83, 65, 82, 69 and 76 will turn into 86, 68, 85, 72 and 79. If you look up the ASCII table, you will see this corresponds to V, D, U, H and O.

However, here we are introduced to a potential problem. What if the starting phrase has letters near the end of the alphabet? What if we used the word WAX with a shift of 5? WAX would turn into ***\F]*** instead of BFC as we expect. So how can we loop around back to the start of the alphabet? **With the modulo operator**.

### Using the Modulo operator

If you have heard of the modulo operator before, you might associate it with checking whether a number is odd or even, or if it is a multiple of another number. However, you can also use the modulo to loop within a range of numbers. If you have never heard of modulo before, it returns the remainder after division, eg. 5 / 2 = 2 remainder 1. So 5 % 2 = 1.

As an example, let's look at a standard, 12-hour clock.

![Clock face by Kiddo Shelter](https://1188845104-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FemqaKEQLvBlmqT5Y4eUS%2Fuploads%2FLHqsaMzgpcEu6KqSBrYz%2Fclockface.jpg?alt=media\&token=f177866d-5ec3-4072-a7dd-fb8780e38669)

If you start at 5 o'clock and add 5 hours, you will have 10 o'clock. Makes sense, right? 5 + 5 = 10.  But what if you start at 9 o'clock? 9 + 5 = 14, but there is no 14 o'clock, there is only 2 o'clock. So how do we get 9 + 5 = 2? By using modulo.

Since there are only 12 hours on a clock, if we take 14 % 12, we will end up with 2.&#x20;

Let's try with another example. 7 o'clock, and moving on 8 hours.

<details>

<summary>Let's try with another example. 7 o'clock, and moving on 8 hours.</summary>

7 + 8 = 15

15 % 12 = 3. We get 3 o'clock.

Remember, we are using % 12 because there are only 12 hours on a clock face.

</details>

<details>

<summary>Let's try one last, crazy example. 8 o'clock, adding 29 hours!</summary>

8 + 29 = 37

37 % 12 = 1. So we will end up at 1 o'clock again.

</details>

And this will also work with any number. Let's add a modulo to our first example of 5 + 5.

5 + 5 = 10

10 % 12 = 10. Since 12 can not divide into 10, the entire 10 is given back as a remainder.

We can apply this to the alphabet as well. Or anything else that needs to "loop around".

Take the 23rd letter of the alphabet (W) and add 6 to it.&#x20;

<details>

<summary>Take the 23rd letter of the alphabet (W) and add 6 to it.</summary>

23 + 6 = 29.

29 % 26 = 3. So we end up with the 3rd letter, or C.

</details>

**This brings us to the next part of our code.**

```python
(ord(character) + shift - 65) % 26 + 65
```

As you saw above, the modulo trick works because we have a logical place value for our characters, for example, A is 1, B is 2, Z is 26, etc. But the `ord()` function returns values starting at 65! To fix that, we simply subtract 65 after we do the shift.&#x20;

So looking at our WAX example,   W, A, X first returns 87, 65, 88. Adding a shift of 5 returns 92, 70, 93. Now, when we subtract 65 from those values we will get 27, 5, 28.

Now we use modulo to try and loop each number back so they are less than 26.&#x20;

27 % 26 = 1.&#x20;

28 % 26 = 2.

So after applying the modulo we will have 1, 5, and 2. All that is left is to add the 65 that we removed earlier back in order to make them valid ASCII numbers again. So we will get 66, 70, 67. Look them up on the ASCII table and you will see that these numbers correspond to **B, F and C**.

Lastly, we need to convert these ASCII values of ours back into characters, and we do this with the `chr()` function.

```python
chr((ord(character) + shift - 65) % 26 + 65)
```

So we just get the `chr()` of all of the previous code and that will return the fully shifted character.

## Creating the cipher tool

Now that we know how our main algorithm works, let's see how we can build a program that utilizes it.

### The plan

We want to create a cipher tool that takes two inputs - a phrase and a key - and returns the secret code. It should look something like this when we are done:

```
Please enter a phrase: Hello Students!
Please enter a key: 7
Your secret code is:
Olssv Zabkluaz!
```

As you can see, our cipher tool only converts characters that are part of the alphabet. So things like spaces and punctuation marks are not converted.

So, where do we get started? By breaking down our program into sub-problems, which makes them easier to deal with.

### The sub-problems

In order to make our program, we need to solve the following problems:

* [Get input from the user](#getting-input-from-the-user)
* [Convert all capital letters](#converting-the-capital-letters)
* [Convert all lower-case letters](#converting-lower-case-letters)
* [Build the secret code](#building-the-secret-code)

Breaking our program down into smaller, more manageable problems makes our lives easier. The wonderful thing about programming is that you don't necessarily have to start at the beginning every time.

### Getting input from the user

This is likely the easiest step in our program and the rest of our program depends on it, so let's get this out of the way first.&#x20;

We will get the input two times, and save the results in variables

<details>

<summary>First try by yourself, and then check the answer.</summary>

```python
original_phrase = input("Please enter a phrase: ")
shift = int(input("Please enter a key: "))
```

</details>

Remember that anything we get from the `input()` function returns a string, and for the shift we actually need an integer, so I immediately enclosed the input for `shift` in an `int()` function, so we don't need to do that later.

And that's it for gathering the input! Now let's start building our functions.

### Converting the capital letters

[Earlier](#explanation) we mentioned that the algorithm for converting capital letters and lowercase letters are a little bit different. For capital letters it is:

```python
chr((ord(character) + shift - 65) % 26 + 65)
```

So let's create a function in which we can use this algorithm every time we come across a capital letter.

<details>

<summary>Try creating a function that returns the shifted character</summary>

```python
def convert_upper(character, shift):
    return chr((ord(character) + shift - 65) % 26 + 65)
```

</details>

We create a new function with the `def` keyword. We want to bring two arguments into our function, the character we want to convert and the shift key we want to convert it by. Then we simply return the converted character.

### Converting lower case letters

Converting lower case letters is very similar. Our core algorithm is:

```python
chr((ord(character) + shift - 97) % 26 + 97)
```

See that the only difference is that the 65 is now a 97, because the ASCII code for a lowercase "a" is 97.

If we create a function similar to above it will look like this:

```python
def convert_lower(character, shift):
    return chr((ord(character) + shift - 97) % 26 + 97)
```

Now we have a function for converting uppercase letters and one for lowercase letters.

{% hint style="info" %}
Technically, we don't have to create functions for these conversions. However, creating them makes our code more readable and easier to work with.
{% endhint %}

### Building the secret code

This is probably the hardest part of the code. Now we need to take our `original_phrase` input, go through it one character at a time, determine whether it is uppercase, lowercase or  non-alphabet, convert it as needed and then build our new secret code.

Before we continue, I will add one more empty variable called `secret_code` in which we will store our final result.

So far, our total code looks like this:

```python
original_phrase = input("Please enter a phrase: ")
shift = int(input("Please enter a key: "))

secret_code = ""

def convert_upper(character, shift):
    return chr((ord(character) + shift - 65) % 26 + 65)
    
def convert_lower(character, shift):
    return chr((ord(character) + shift - 97) % 26 + 97)
```

Now we will add a `for` loop that goes over each character in the phrase, checks whether it is part of the alphabet, then checks whether it is uppercase or lowercase so we can call the correct function and finally add the converted character into our `secret_code` variable.

<details>

<summary>This one is tricky. Try by yourself first before you check the answer.</summary>

```python
for character in original_phrase:
    if character.isalpha() == True:
        if character.isupper() == True:
            secret_code = secret_code + convert_upper(character, shift)
        else:
            secret_code = secret_code + convert_lower(character, shift)
    else:
        secret_code = secret_code + character
```

</details>

Let's go over each line of the above code and what it does:

1. We create a `for` loop that gets each character in our original phrase.
2. We check if this character is part of the alphabet using the `isalpha()` function.
3. If it is part of the alphabet, we check whether it is uppercase with the `isupper()` function.
4. We run that character through our uppercase converter and we add the result to the end of our secret code.
5. If that character is not uppercase
6. Then run it through our lowercase converter and add it to the end of our final result.
7. If the character is not part of the alphabet
8. We simply add it to the end of our final result.

With our for loop done, our code so far looks like this:

```python
original_phrase = input("Please enter a phrase: ")
shift = int(input("Please enter a key: "))

secret_code = ""

def convert_upper(character, shift):
    return chr((ord(character) + shift - 65) % 26 + 65)
    
def convert_lower(character, shift):
    return chr((ord(character) + shift - 97) % 26 + 97)

for character in original_phrase:
    if character.isalpha() == True:
        if character.isupper() == True:
            secret_code = secret_code + convert_upper(character, shift)
        else:
            secret_code = secret_code + convert_lower(character, shift)
    else:
        secret_code = secret_code + character
```

Just one more step left, we add `print(secret_code)` all the way at the end of our program.

```python
original_phrase = input("Please enter a phrase: ")
shift = int(input("Please enter a key: "))

secret_code = ""

def convert_upper(character, shift):
    return chr((ord(character) + shift - 65) % 26 + 65)
    
def convert_lower(character, shift):
    return chr((ord(character) + shift - 97) % 26 + 97)

for character in original_phrase:
    if character.isalpha() == True:
        if character.isupper() == True:
            secret_code = secret_code + convert_upper(character, shift)
        else:
            secret_code = secret_code + convert_lower(character, shift)
    else:
        secret_code = secret_code + character
        
print(secret_code)
```

Let's go over each line one by one again.

1. Asks the user to input a phrase and then saves this phrase in a variable called `original_phrase`.
2. Asks the user for a key. We then convert that key to an integer and save it in a variable called `shift`.
3. blank
4. We create a variable called `secret_code`, and make it an empty string. This is because we will add the converted characters one by one to build our secret code.
5. blank
6. We define a function called `convert_upper` which takes two arguments, character and shift.
7. This function runs our algorithm and returns the result. We can use this result to do something else.
8. blank
9. We create another function called `convert_lower`, which also takes two arguments, character and shift.
10. This function runs our algorithm and returns the result. We can use this result to do something else.
11. blank
12. This for loop goes over each character in our `original phrase`, one by one, and then runs the code below on that character.
13. We check if this character is part of the alphabet using the `isalpha()` function.
14. If it is part of the alphabet, we check whether it is uppercase with the `isupper()` function.
15. We run that character through our uppercase converter, using the `character` variable from the loop, and our `shift` from the input, and we add the result to the end of our `secret_code`.
16. If that character is not uppercase
17. Then run it through our lowercase converter and add it to the end of our final result.
18. If the character is not part of the alphabet
19. We simply add it to the end of our final result.
20. blank
21. We print the secret code.

### Conclusion

And that is it!

This project teaches you a lot of the core skills you need as a beginner programmer in one short exercise. Remember to add comments to your code when doing it on your own so that you don't forget what certain pieces of code do.

Lastly, do me a favour and rate this tutorial at the bottom of the page!
