Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Alphabet

```python
AlPHABET = "abcdefghijklmnopqrstuvwxyz"
ALPHABET = "abcdefghijklmnopqrstuvwxyz"

def rotate(text, key):
result = ""
for letter in text:
if letter.isalpha():
if letter.isupper():
result += AlPHABET[(AlPHABET.index(letter.lower()) + key) % 26].upper()
result += ALPHABET[(ALPHABET.index(letter.lower()) + key) % 26].upper()
else:
result += AlPHABET[(AlPHABET.index(letter) + key) % 26]
result += ALPHABET[(ALPHABET.index(letter) + key) % 26]
else:
result += letter
return result
Expand All @@ -22,9 +22,9 @@ The function `rotate()` is then declared, and a variable `result` is defined as
The text argument is then iterated over via a [`for loop`][for-loop].
Each element is checked to make sure it is a letter, and subsequently checked if it is uppercase or lowercase.
Uppercase letters are converted to lowercase.
Then the index of each letter is found in the `AlPHABET` constant.
Then the index of each letter is found in the `ALPHABET` constant.
The numeric key value is added to the letter index and [modulo (`%`)][modulo] 26 is used on the result.
Finally, the new number is used as an index into the `AlPHABET` constant, and the resulting letter is converted back to uppercase.
Finally, the new number is used as an index into the `ALPHABET` constant, and the resulting letter is converted back to uppercase.

Lowercase letters follow the same process without the conversion steps.

Expand All @@ -36,7 +36,7 @@ If only English letters are needed, the constant [`string.ascii_lowercase`][asci
```python
from string import ascii_lowercase

AlPHABET = ascii_lowercase
ALPHABET = ascii_lowercase
```

[ascii_lowercase]: https://docs.python.org/3/library/string.html#string.ascii_letters
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
for letter in text:
if letter.isalpha():
if letter.isupper():
result += AlPHABET[(AlPHABET.index(letter.lower()) + key) % 26].upper()
result += ALPHABET[(ALPHABET.index(letter.lower()) + key) % 26].upper()
else:
result += AlPHABET[(AlPHABET.index(letter) + key) % 26]
result += ALPHABET[(ALPHABET.index(letter) + key) % 26]
else:
result += letter
11 changes: 7 additions & 4 deletions exercises/practice/rotational-cipher/.approaches/config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"introduction": {
"authors": ["meatball133", "bethanyg"],
"contributors": []
"contributors": ["yrahcaz7"]
Comment thread
BethanyG marked this conversation as resolved.
},
"approaches": [
{
Expand All @@ -16,21 +16,24 @@
"slug": "alphabet",
"title": "Alphabet",
"blurb": "Using the alphabet to rotate the alphabet",
"authors": ["meatball133", "bethanyg"]
"authors": ["meatball133", "bethanyg"],
"contributors": ["yrahcaz7"]
},
{
"uuid": "e539d1a5-f497-402b-a232-7e889f4323c1",
"slug": "str-translate",
"title": "Str Translate",
"blurb": "Using str.translate to rotate the alphabet",
"authors": ["meatball133", "bethanyg"]
"authors": ["meatball133", "bethanyg"],
"contributors": ["yrahcaz7"]
},
{
"uuid": "0c74890e-d96e-47a2-a8bf-93c45dd67f94",
"slug": "recursion",
"title": "Recursion",
"blurb": "Using Recursion to rotate the alphabet",
"authors": ["meatball133", "bethanyg"]
"authors": ["meatball133", "bethanyg"],
"contributors": ["yrahcaz7"]
}
]
}
18 changes: 9 additions & 9 deletions exercises/practice/rotational-cipher/.approaches/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,16 @@ Here, if we want to use the Scandinavian letter: **å**, we can simply insert it

```python
# This only uses English characters
AlPHABET = "abcdefghijklmnopqrstuvwxyz"
ALPHABET = "abcdefghijklmnopqrstuvwxyz"

def rotate(text, key):
result = ""
for letter in text:
if letter.isalpha():
if letter.isupper():
result += AlPHABET[(AlPHABET.index(letter.lower()) + key) % 26].upper()
result += ALPHABET[(ALPHABET.index(letter.lower()) + key) % 26].upper()
else:
result += AlPHABET[(AlPHABET.index(letter) + key) % 26]
result += ALPHABET[(ALPHABET.index(letter) + key) % 26]
else:
result += letter
return result
Expand All @@ -82,11 +82,11 @@ The benefit of this approach is that it has no visible loop, making the code mor


```python
AlPHABET = "abcdefghijklmnopqrstuvwxyz"
ALPHABET = "abcdefghijklmnopqrstuvwxyz"

def rotate(text, key):
translator = AlPHABET[key:] + AlPHABET[:key]
return text.translate(str.maketrans(AlPHABET + AlPHABET.upper(), translator + translator.upper()))
translator = ALPHABET[key:] + ALPHABET[:key]
return text.translate(str.maketrans(ALPHABET + ALPHABET.upper(), translator + translator.upper()))
```

For more information, check out the [Str translate approach][approach-str-translate].
Expand All @@ -106,17 +106,17 @@ Calculate your base case carefully to avoid errors.


```python
AlPHABET = "abcdefghijklmnopqrstuvwxyz"
ALPHABET = "abcdefghijklmnopqrstuvwxyz"

def rotate(text, key):
if text == "":
return ""
first_letter, rest = text[0], text[1:]
if first_letter.isalpha():
if first_letter.isupper():
return AlPHABET[(AlPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate(rest, key)
return ALPHABET[(ALPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate(rest, key)
else:
return AlPHABET[(AlPHABET.index(first_letter) + key) % 26] + rotate(rest, key)
return ALPHABET[(ALPHABET.index(first_letter) + key) % 26] + rotate(rest, key)
else:
return first_letter + rotate(rest, key)
```
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Recursion

```python
AlPHABET = "abcdefghijklmnopqrstuvwxyz"
ALPHABET = "abcdefghijklmnopqrstuvwxyz"

def rotate(text, key):
if text == "":
return ""
first_letter, rest = text[0], text[1:]
if first_letter.isalpha():
if first_letter.isupper():
return AlPHABET[(AlPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate(rest, key)
return ALPHABET[(ALPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate(rest, key)
else:
return AlPHABET[(AlPHABET.index(first_letter) + key) % 26] + rotate(rest, key)
return ALPHABET[(ALPHABET.index(first_letter) + key) % 26] + rotate(rest, key)
else:
return first_letter + rotate(rest, key)
```
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
first_letter, rest = text[0], text[1:]
if first_letter.isalpha():
if first_letter.isupper():
return AlPHABET[(AlPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate(rest, key)
return ALPHABET[(ALPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate(rest, key)
else:
return AlPHABET[(AlPHABET.index(first_letter) + key) % 26] + rotate(rest, key)
return ALPHABET[(ALPHABET.index(first_letter) + key) % 26] + rotate(rest, key)
else:
return first_letter + rotate(rest, key)
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Str Translate

```python
AlPHABET = "abcdefghijklmnopqrstuvwxyz"
ALPHABET = "abcdefghijklmnopqrstuvwxyz"

def rotate(text, key):
translator = AlPHABET[key:] + AlPHABET[:key]
return text.translate(str.maketrans(AlPHABET + AlPHABET.upper(), translator + translator.upper()))
translator = ALPHABET[key:] + ALPHABET[:key]
return text.translate(str.maketrans(ALPHABET + ALPHABET.upper(), translator + translator.upper()))
```

This approach uses the [`<str>.translate`][translate] method.
Expand All @@ -14,18 +14,18 @@ To create a translation table we use [`str.makestrans`][maketrans].

This approach starts with defining a constant of all the lowercase letters in the alphabet.
Then the function `rotate()` is declared.
A `translator` variable defined with the value of the `AlPHABET` constant [sliced][slicing] from the key to the end and then sliced from the start to the key.
A `translator` variable defined with the value of the `ALPHABET` constant [sliced][slicing] from the key to the end and then sliced from the start to the key.

This is done so we have 2 strings which are the same but shifted by the key value.
Say we have the `AlPHABET` constant with the value of `abcdefghijklmnopqrstuvwxyz` and the key is 3.
Say we have the `ALPHABET` constant with the value of `abcdefghijklmnopqrstuvwxyz` and the key is 3.
Then the `translator` variable will have the value of `defghijklmnopqrstuvwxyzabc`.

`str.translate` is then called on the `text` argument.
`str.translate` takes a translation table mapping start values to transformed values as an argument.
To create a translation table, `str.makestrans` is used.
`makestrans` takes 2 arguments: the first is the string to be translated, and the second is the string the first argument should be translated to.

For our solution, the first argument is the `AlPHABET` constant + the `AlPHABET` constant in uppercase.
For our solution, the first argument is the `ALPHABET` constant + the `ALPHABET` constant in uppercase.
The second argument is the `translator` variable + uppercase `translator` variable.

`str.makestrans` takes the [Unicode][unicode] values of the first argument and maps them to the corresponding Unicode values in the second argument, creating a `dict`.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
AlPHABET = "abcdefghijklmnopqrstuvwxyz"
ALPHABET = "abcdefghijklmnopqrstuvwxyz"

def rotate(text, key):
translator = AlPHABET[key:] + AlPHABET[:key]
return text.translate(str.maketrans(AlPHABET + AlPHABET.upper(), translator + translator.upper()))
translator = ALPHABET[key:] + ALPHABET[:key]
return text.translate(str.maketrans(ALPHABET + ALPHABET.upper(), translator + translator.upper()))
3 changes: 2 additions & 1 deletion exercises/practice/rotational-cipher/.articles/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"slug": "performance",
"title": "Performance deep dive",
"blurb": "Deep dive to find out the performance between different approaches",
"authors": ["meatball133", "bethanyg"]
"authors": ["meatball133", "bethanyg"],
"contributors": ["yrahcaz7"]
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
print(sys.version)


AlPHABET = "abcdefghijklmnopqrstuvwxyz"
COMBINATIONS = itertools.combinations_with_replacement(f"{AlPHABET[:13]}{AlPHABET[:13].upper()} 12,", 2)
ALPHABET = "abcdefghijklmnopqrstuvwxyz"
COMBINATIONS = itertools.combinations_with_replacement(f"{ALPHABET[:13]}{ALPHABET[:13].upper()} 12,", 2)
TEST_TEST = "".join([element for sublist in COMBINATIONS for element in sublist])

def rotate_ascii(text, key):
Expand All @@ -28,17 +28,17 @@ def rotate_alphabet(text, key):
for letter in text:
if letter.isalpha():
if letter.isupper():
result += AlPHABET[(AlPHABET.index(letter.lower()) + key) % 26].upper()
result += ALPHABET[(ALPHABET.index(letter.lower()) + key) % 26].upper()
else:
result += AlPHABET[(AlPHABET.index(letter) + key) % 26]
result += ALPHABET[(ALPHABET.index(letter) + key) % 26]
else:
result += letter
return result


def rotate_translate(text, key):
translator = AlPHABET[key:] + AlPHABET[:key]
return text.translate(str.maketrans(AlPHABET + AlPHABET.upper(), translator + translator.upper()))
translator = ALPHABET[key:] + ALPHABET[:key]
return text.translate(str.maketrans(ALPHABET + ALPHABET.upper(), translator + translator.upper()))


def rotate_recursion(text, key):
Expand All @@ -47,9 +47,9 @@ def rotate_recursion(text, key):
first_letter, rest = text[0], text[1:]
if first_letter.isalpha():
if first_letter.isupper():
return AlPHABET[(AlPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate_recursion(rest, key)
return ALPHABET[(ALPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate_recursion(rest, key)
else:
return AlPHABET[(AlPHABET.index(first_letter) + key) % 26] + rotate_recursion(rest, key)
return ALPHABET[(ALPHABET.index(first_letter) + key) % 26] + rotate_recursion(rest, key)
else:
return first_letter + rotate_recursion(rest, key)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ For a short string as input, is the alphabet approach the fastest, followed by a
This means that if you know the input is a short string, the fastest approach is to use the alphabet, and forgo the overhead of making and saving a translation dictionary.
On the other hand, if the input is a long string, the overhead of making a dictionary is amortized over the length of the text to be translated, and the fastest approach becomes `str.translate`.

[approaches]: https://exercism.org/tracks/python/exercises/rotational-cipher/dig_deeper
[approach-recursion]: https://exercism.org/tracks/python/exercises/rotational-cipher/approaches/recursion
[approach-str-translate]: https://exercism.org/tracks/python/exercises/rotational-cipher/approaches/str-translate
[approach-ascii-values]: https://exercism.org/tracks/python/exercises/rotational-cipher/approaches/ascii-values
Expand Down
Loading