Skip to content

Rotational Cipher: Exercise Added #460

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 3, 2017
Merged
Show file tree
Hide file tree
Changes from 6 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
9 changes: 9 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@
"topics": [
]
},
{
"slug": "rotational-cipher",
"difficulty": 1,
"topics": [
"strings",
"logic",
"control-flow (loops)"
]
},
{
"slug": "difference-of-squares",
"difficulty": 1,
Expand Down
2 changes: 2 additions & 0 deletions exercises/rotationa-cipher
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def rotational_cipher():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this file was exceedingly created (at least it's not needed) and should be removed.

pass
12 changes: 12 additions & 0 deletions exercises/rotational-cipher/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
def rotational_cipher(message, key):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention is to use nouns for classes and verbs for functions. So in this case I would prefer rotate().

import string
alpha_lower = list(string.ascii_lowercase)
alpha_upper = list(string.ascii_uppercase)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of creating the alpha variables, you could rename them inside the import statement like this:

from string import ascii_lowercase as alpha_lower
from string import ascii_uppercase as alpha_upper
``

coded_message = ""
for char in list(message):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The python strings already support the sequence type methods, so you don't need to convert them to lists to use for or index().

if char in alpha_lower:
char = alpha_lower[(alpha_lower.index(char) + key) % 26]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could create a constant for the length of alphabet ALPHA_LEN = len(alpha_lower). In this case it would also work if the ascii alphabet is changed, which is totally unlikely to happen. So, using 26 is fine as well.

elif char in alpha_upper:
char = alpha_upper[(alpha_upper.index(char) + key) % 26]
coded_message = coded_message + char
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be shortened with coded_message += char.

return coded_message
14 changes: 14 additions & 0 deletions exercises/rotational-cipher/rotational_cipher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a description in the markdown file, so I wouldn't add any doc string here. We tend to keep the stub files very limited, so we don't force any specific way of implementing an exercise or naming parameters onto the users. This should be enough:

def rotate():
    pass


def rotational_cipher(message, key):
"""Preform a rotation cipher on a message.

Arguments:
message -- Message to be incoded in the form of a string
key -- The number of letters the charactors are to be shifted

Outputs:
coded_message -- A string containing the transposed message
"""
coded_message = ""
return coded_message
55 changes: 55 additions & 0 deletions exercises/rotational-cipher/rotational_cipher_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import unittest

import rotational_cipher


class RotationalCipher(unittest.TestCase):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We try to stick to the canonical test data provided in the x-common repository.

If you are missing a test case that would make sense for all tracks, than it would be best to also add it there.
If you think we need an additional test case that would be python specific it would be good to mark those with a comment (# additional track specific tests) to make it easy to compare it against the common test cases.

def test_hello(self):
self.assertEqual(rotational_cipher.rotational_cipher('hello', 0),
'hello')

def test_space(self):
self.assertEqual(
rotational_cipher.rotational_cipher(
'from the other side',
0),
'from the other side')

def test_ciphered(self):
self.assertEqual(
rotational_cipher.rotational_cipher(
'i must have called',
13),
'v zhfg unir pnyyrq')

def test_mixed(self):
self.assertEqual(
rotational_cipher.rotational_cipher(
'... a 1000 TIMES',
13),
'... n 1000 GVZRF')

def test_emptystring(self):
self.assertEqual(rotational_cipher.rotational_cipher('', 13), '')

def test_numbers(self):
self.assertEqual(rotational_cipher.rotational_cipher('07041776!!%$$', 13),
'07041776!!%$$')

def test_mixed(self):
self.assertEqual(
rotational_cipher.rotational_cipher(
"Doesn't tear you apart;",
27),
"Epfto'u ufbs zpv bqbsu;")

def test_mixed(self):
self.assertEqual(
rotational_cipher.rotational_cipher(
"Anymoreeee :'(",
-26),
"Anymoreeee :'(")


if __name__ == '__main__':
unittest.main()
27 changes: 16 additions & 11 deletions exercises/say/say_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
from say import say


# test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0

class SayTest(unittest.TestCase):
def test_zero(self):
self.assertEqual(say(0), "zero")

def test_one(self):
self.assertEqual(say(1), "one")

Expand All @@ -19,6 +24,7 @@ def test_twenty_two(self):
def test_one_hundred(self):
self.assertEqual(say(100), "one hundred")

# additional track specific test
def test_one_hundred_twenty(self):
self.assertEqual(say(120), "one hundred and twenty")

Expand All @@ -31,12 +37,14 @@ def test_one_thousand(self):
def test_one_thousand_two_hundred_thirty_four(self):
self.assertEqual(say(1234), "one thousand two hundred and thirty-four")

# additional track specific test
def test_eight_hundred_and_ten_thousand(self):
self.assertEqual(say(810000), "eight hundred and ten thousand")

def test_one_million(self):
self.assertEqual(say(1e6), "one million")

# additional track specific test
def test_one_million_two(self):
self.assertEqual(say(1000002), "one million and two")

Expand All @@ -48,24 +56,21 @@ def test_1002345(self):
def test_one_billion(self):
self.assertEqual(say(1e9), "one billion")

def test_number_to_large(self):
with self.assertRaises(AttributeError):
say(1e12)

def test_number_negative(self):
with self.assertRaises(AttributeError):
say(-42)

def test_zero(self):
self.assertEqual(say(0), "zero")

def test_987654321123(self):
self.assertEqual(
say(987654321123), ("nine hundred and eighty-seven billion "
"six hundred and fifty-four million "
"three hundred and twenty-one thousand "
"one hundred and twenty-three"))

def test_number_to_large(self):
with self.assertRaises(AttributeError):
say(1e12)

def test_number_negative(self):
with self.assertRaises(AttributeError):
say(-1)


if __name__ == '__main__':
unittest.main()