You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: exercises/practice/rotational-cipher/.approaches/ascii-values/content.md
+30-23Lines changed: 30 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,37 +14,44 @@ def rotate(text, key):
14
14
return result
15
15
```
16
16
17
-
This approach uses [ascii values][ascii], ascii stands for American Standard Code for Information Interchange.
18
-
It is a character encoding standard for electronic communication.
19
-
It is a 7-bit code, which means that it can represent 128 different characters.
20
-
The system uses numbers to represent various characters, symbols, and other entities.
17
+
This approach uses [ascii values][ascii].
18
+
ASCII stands for **A**merican **S**tandard **C**ode for **I**nformation **I**nterchange.
19
+
It is a 7-bit character encoding standard for electronic communication first described in 1969, becoming a formal standard in 2015.
20
+
It uses numbers to represent 128 different entities including carriage returns, whitespace characters, box characters, alphabetic characters, punctuation, and the numbers 0-9.
21
21
22
-
In ascii can you find all the downcased letter in the range between 97 and 123.
23
-
While the upcased letters are in the range between 65 and 91.
22
+
In ascii, all the lowercase English letters appear between 97 and 123.
23
+
While the uppercase letters are in the range between 65 and 91.
24
24
25
-
The reason why you might not want to do this approach is that it only supports the english alphabet.
25
+
~~~~exercism/caution
26
26
27
-
The approach starts with defining the function `rotate`, then a variable `result` is defined with the value of an empty string.
28
-
Then is all the letters from the text argument iterated over through a [`for loop`][for-loop].
29
-
Then is checked if the letter is a letter, if it is a letter then is checked if it is a uppercased letter.
27
+
This approach only supports the English alphabet.
28
+
Non-English alphabets are not contiguous in their ascii number ranges, and are not consistently defined across platforms.
29
+
For example, the Scandinavian letter: **å** has the extended ascii value of 132, but is used in combination with Latin characters that appear in the 65-91 and 97-123 ranges.
30
+
This means that a shift for an extended ascii word containing **å** won't result in an accurate alphabet position for a Scandinavian language.
30
31
31
-
Python has a built in function called `ord` that converts a [unicode][unicode] symbol to an integer.
32
-
The unicode's first 128 characters are the same as ascii.
32
+
~~~~
33
33
34
-
If it is a uppercased letter then is [`ord`][ord] used to convert the letters to an integer and is then added with the key and then subtracted with 65.
35
-
Then is the result of that [modulo (`%`)][modulo] 26 added with 65.
36
34
37
-
That is because we want to know which index in the alphabet the letter is.
38
-
And if the number is over 26 we want to make sure that it is in the range of 0-26.
39
-
So we use modulo to make sure it is in that range.
40
-
To use modulo for a range we have to make sure that it starts at zero, thereby are we subtracting the integer value of the letter with 65.
41
-
After that to get the back to a letter we add 65 and use the [`chr`][chr] method which converts an an unicode value to a letter.
42
-
After that is the new letter added to the result.
35
+
The approach starts with defining the function `rotate()`, with a variable `result` is assigned to an empty string.
36
+
The elements of the text argument are then iterated over using a [`for loop`][for-loop].
37
+
Each element is checked to see if it is a letter, and then is checked if it is an uppercase letter.
43
38
44
-
If the letter is a lowercased letter then is the same done but with the ascii value of 97 subtracted with the letter.
39
+
Python has a builtin function called `ord` that converts a [unicode][unicode] symbol to an integer representation.
40
+
Unicode's first 128 code points have the same numbers as their ascii counterparts.
45
41
46
-
If the letter is not a letter then is the letter added to the result.
47
-
When the loop is finished we return the result.
42
+
If the element is an uppercase letter, [`ord`][ord] is used to convert the letter to an integer.
43
+
The integer is added to the numeric key and then 65 is subtracted from the total.
44
+
Finally, the result is [modulo (`%`)][modulo] 26 (_to put the value within the 2) and 65 is added back.
45
+
46
+
This is because we want to know which letter of the alphabet the number will become.
47
+
And if the new number is over 26 we want to make sure that it "wraps around" to remain in the range of 0-26.
48
+
To properly use modulo for a range we have to make sure that it starts at zero, so we subtract 65.
49
+
To get back to a letter in the asciii range we add 65 and use the [`chr`][chr] method to convert the value to a letter.
50
+
51
+
The process is the same for a lowercase letter, but with 97 subtracted to put the letter in the lowercase ascii range of 97 - 123.
52
+
53
+
Any element that is not a letter (_whitespace or punctuation_) is added directly to the result string.
54
+
When all the elements have been looped over, the full result is returned.
Copy file name to clipboardExpand all lines: exercises/practice/rotational-cipher/.approaches/introduction.md
+45-20Lines changed: 45 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,22 +1,30 @@
1
1
# Introduction
2
2
3
3
There are various ways to solve `rotational-cipher`.
4
-
You can for example use a [ascii values][ascii], alphabet, recursion, and `str.translate`.
4
+
You can for example use [ascii values][ascii], an alphabet `str` or `list`, recursion, or `str.translate`.
5
+
5
6
6
7
## General guidance
7
8
8
-
The goal of this exercise is to rotate the letters in a string by a given key.
9
+
The goal of this exercise is to shift the letters in a string by a given integer key between 0 and 26.
10
+
The letter in the encrypted string is shifted for as many values (or "positions") as the value of the key.
9
11
10
12
## Approach: Using ascii values
11
13
12
-
This approach is very simple and easy to understand.
13
-
it uses the ascii value of the letters to rotate them.
14
-
There the numbers 65-91 in the ascii range represent downcased letters.
15
-
While 97-123 represent upcased letters.
14
+
This approach is straightforward to understand.
15
+
It uses the ascii value of the letters to rotate them within the message.
16
+
The numbers 65-91 in the ascii range represent lowercase Latin letters, while 97-123 represent uppercase Latin letters.
17
+
18
+
19
+
~~~~exercism/caution
20
+
21
+
This approach only supports the English alphabet.
22
+
Non-English alphabets are not contiguous in their ascii number ranges, and are not consistently defined across platforms.
23
+
For example, the Scandinavian letter: **å** has the extended ascii value of 132, but is used in combination with Latin characters that appear in the 65-91 and 97-123 ranges.
24
+
This means that a shift for an extended ascii word containing **å** won't result in an accurate alphabet position for a Scandinavian language.
25
+
26
+
~~~~
16
27
17
-
The reason why you might not want to do this approach is that it only supports the english alphabet.
18
-
Say we want to use the scandinavian letter: **å**, then this approach will not work.
19
-
Since **å** has the ascii value of 132.
20
28
21
29
```python
22
30
defrotate(text, key):
@@ -34,16 +42,20 @@ def rotate(text, key):
34
42
35
43
For more information, check the [ascii values approach][approach-ascii-values].
36
44
45
+
37
46
## Approach: Alphabet
38
47
39
-
This approach is similar to the previous one, but instead of using the ascii values, it uses the index of the letter in the alphabet.
40
-
It requires the storing of a string and unless you are using two strings you have to convert the letters from upper to lower case.
48
+
This approach is similar to the ascii one, but it uses the index number of each letter in an alphabet string.
49
+
It requires making a string for all the letters in an alphabet.
50
+
And unless two strings are used, you will have to convert individual letters from lower to upper case (or vice-versa).
51
+
52
+
The big advantage of this approach is the ability to use any alphabet (_although there are some issues with combining characters in Unicode._).
53
+
Here, if we want to use the scandinavian letter: **å**, we can simply insert it into our string where we want it:
54
+
`abcdefghijklmnopqrstuvwxyzå` and the rotation will work correctly.
41
55
42
-
What this approach although give is the possibility to use any alphabet.
43
-
Say we want to use the scandinavian letter: **å**, then we just add it where we want it:
44
-
`abcdefghijklmnopqrstuvwxyzå` and it will rotate correctly around that.
45
56
46
57
```python
58
+
# This only uses English characters
47
59
AlPHABET ="abcdefghijklmnopqrstuvwxyz"
48
60
49
61
defrotate(text, key):
@@ -61,14 +73,19 @@ def rotate(text, key):
61
73
62
74
For more information, check the [Alphabet approach][approach-alphabet].
63
75
76
+
64
77
## Approach: Str translate
65
78
66
-
This approach is similar to the previous one, but instead of using the index of the letter in the alphabet, it uses the `str.translate` method.
67
-
The benefit of this approach is that it has no visible loop, thereby the code becomes more concise.
68
-
What to note is that the `str.translate` still loops over the `string` thereby even if it is no visible loop, it doesn't mean that a method is not looping.
79
+
This approach uses the [`str.translate`][str-translate] method to create a mapping from input to shifted string instead of using the index of an alphabet string to calculate the shift.
80
+
The benefit of this approach is that it has no visible loop, making the code more concise.
81
+
82
+
~~~~exercism/note
83
+
`str.translate` **still loops over the `string`** even if it is not visibly doing so.
84
+
~~~~
85
+
69
86
70
87
```python
71
-
AlPHABET ="abcdefghijklmnopqrstuvwxyz"
88
+
AlPHABET ="abcdefghijklmnopqrstuvwxyz
72
89
73
90
defrotate(text, key):
74
91
translator = AlPHABET[key:] + AlPHABET[:key]
@@ -77,13 +94,19 @@ def rotate(text, key):
77
94
78
95
For more information, check the [Str translate approach][approach-str-translate].
79
96
97
+
80
98
## Approach: Recursion
81
99
82
-
In this approach we use a recursive function.
100
+
This approach uses a recursive function.
83
101
A recursive function is a function that calls itself.
84
102
This approach can be more concise than other approaches, and may also be more readable for some audiences.
85
103
86
-
The reason why you might not want to use this approach is that Python has a [recursion limit][recursion-limit] with a default of 1000.
104
+
105
+
~~~~exercism/caution
106
+
Python does not have any tail-call optimization and has a default [recursion limit][recursion-limit] of 1000 calls on the stack.
107
+
Calculate your base case carefully to avoid errors.
108
+
~~~~
109
+
87
110
88
111
```python
89
112
AlPHABET ="abcdefghijklmnopqrstuvwxyz"
@@ -103,6 +126,7 @@ def rotate(text, key):
103
126
104
127
For more information, check the [Recursion approach][approach-recursion].
105
128
129
+
106
130
## Benchmark
107
131
108
132
For more information, check the [Performance article][article-performance].
@@ -114,3 +138,4 @@ For more information, check the [Performance article][article-performance].
Copy file name to clipboardExpand all lines: exercises/practice/rotational-cipher/.approaches/recursion/content.md
+11-9Lines changed: 11 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,23 +16,25 @@ def rotate(text, key):
16
16
return first_letter + rotate(rest, key)
17
17
```
18
18
19
-
This approach uses a very similar approach to alphabet.
20
-
And uses the same logic but instead of a loop so does this approach use [concept:python/recursion]() to solve the problem.
19
+
This approach uses the same logic as that of the `alphabet` approach, but instead of a `loop`, [concept:python/recursion]() is used to parse the text and solve the problem.
21
20
22
21
Recursion is a programming technique where a function calls itself.
23
-
It is a powerful technique, but can be more tricky to implement than a while loop.
24
-
Recursion isn't that common in Python, it is more common in functional programming languages, like:[Elixir][elixir], [Haskell][haskell], and [Clojure][clojure].
22
+
It is powerful, but can be more tricky to implement than a `while loop` or `for loop`.
23
+
Recursive techniques are more common in functional programming languages like [Elixir][elixir], [Haskell][haskell], and [Clojure][clojure] than they are in Python.
25
24
26
-
Solving this exercise with recursion removes the need for a "result" variable and the instantiation of a `loop`.
25
+
Solving this exercise with recursion removes the need for a `result` variable and the instantiation of a `loop`.
27
26
If the number is not equal to one, we call `<letter> + rotate(rest)`.
28
27
Then the `rotate` function can execute the same code again with new values.
29
-
Meaning we can get a long chain or stack of `<letter> + rotate(rest)` until the rest variable is exhausted and then the code adds `""`.
28
+
We can build a long chain or "stack" of `<letter> + rotate(rest)`calls until the `rest` variable is exhausted and the code adds `""`.
30
29
That translates to something like this: `<letter> + <letter> + <letter> + <letter> + ""`.
31
30
32
-
In Python, we can't have a function call itself more than 1000 times by default.
33
-
Code that exceeds this recursion limit will throw a [RecursionError][recursion-error].
34
-
While it is possible to adjust the [recursion limit][recursion-limit], doing so risks crashing Python and may also crash your system.
31
+
32
+
~~~~exercism/note
33
+
By default, we can't have a function call itself more than 1000 times.
34
+
Code that exceeds this recursion limit will throw a RecursionError.
35
+
While it is possible to adjust the recursion limit, doing so risks crashing Python and may also crash your system.
35
36
Casually raising the recursion limit is not recommended.
This approach uses the [`<str>.translate`][translate] method to solve the problem.
11
+
This approach uses the [`<str>.translate`][translate] method.
12
12
`translate` takes a translation table as an argument.
13
13
To create a translation table we use [str.`makestrans`][maketrans].
14
14
15
-
The approach starts with defining the a constant which holds the whole alphabets lowercase letters.
16
-
Then the function `rotate` is declared.
17
-
Then is the `translator` variable defined with the value of the `AlPHABET` constant [sliced][slicing] from the key to the end and then the `AlPHABET` constant sliced from the start to the key.
15
+
This approach starts with defining a constant of all the lowercase letters in the alphabet.
16
+
Then the function `rotate()` is declared.
17
+
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.
18
18
19
-
This is done so we have 2 strings which are the same but shifted by the key.
19
+
This is done so we have 2 strings which are the same but shifted by the key value.
20
20
Say we have the `AlPHABET` constant with the value of `abcdefghijklmnopqrstuvwxyz` and the key is 3.
21
21
Then the `translator` variable will have the value of `defghijklmnopqrstuvwxyzabc`.
22
22
23
-
Then is the `translate` method called on the `text` argument.
24
-
The `translate` method takes a translation table as an argument.
25
-
To create a translation table we use str.`makestrans`maketrans.
23
+
`str.translate` is then called on the `text` argument.
24
+
`str.translate` takes a translation table mapping start values to transformed values as an argument.
25
+
To create a translation table, `str.makestrans` is used.
26
+
`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.
26
27
27
-
The `makestrans` method takes 2 arguments.
28
-
The first argument is the string which holds the characters which should be translated.
29
-
The second argument is the string which holds the characters which the characters from the first argument should be translated to.
28
+
For our solution, the first argument is the `AlPHABET` constant + the `AlPHABET` constant in uppercase.
29
+
The second argument is the `translator` variable + uppercase `translator` variable.
30
30
31
-
The first argument is the `AlPHABET` constant and the `AlPHABET` constant uppercased.
32
-
The second argument is the `translator` variable and the `translator` variable uppercased.
31
+
`makestrans` does is that it takes the [Unicode][unicode] values of the first argument and maps them to the corresponding Unicode values in the second argument, creating a `dict`.
33
32
34
-
What the `makestrans` does is that it takes the first argument and maps it to the second argument.
35
-
It does that by creating a [dictionary], and converting the letter to [unicode][unicode].
36
33
37
34
```python
38
35
>>>str.maketrans("abc", "def")
39
36
{97: 100, 98: 101, 99: 102}
40
37
```
41
38
42
-
The `translate`method takes the dictionary created by the `makestrans`method and uses it to translate the characters in the `text` argument.
39
+
`str.translate` takes the `dict` created by `str.makestrans` and uses it to translate the characters in the `text` argument.
43
40
44
41
```python
45
42
>>>"abc".translate({97: 100, 98: 101, 99: 102})
46
43
'def'
47
44
```
48
45
49
-
When the loop is finished we return the result.
46
+
Once the `str.translate`loop completes, we return the `result`.
0 commit comments