Simple Cipher instructions are unclear

The instruction given does not provide sufficient information on how the algorithm works.
(1) when ‘aaaaaaaaaaaaaaaaaa’ is provided as key, what algorithm does it go through to encode? What determines the a = 0 setting?
(2) When ‘ddddddddddddddddd’ is provided as key, what would happen differently in encoding?
(3) Why setting the key to ‘dddd’ would result in Caesar Cipher?

For someone without prior knowledge on cryptology, it is impossible to finish this exercise.

The key tells you how much to shift the letters. a = 0 and d = 4. Those values are the shift distance.

The d refers to the prior description of the Caesar Cipher:

If anyone wishes to decipher these, and get at their meaning, he must substitute the fourth letter of the alphabet, namely D, for A, and so with the others.

Does that help you figure out how to complete the exercise?

@J-ZW-Wang Did you take a look at the tests? Not the tests results I mean, but the tests themselves. I find this often helps.

I agree the instructions could use some clarification. Do you have suggestions?

It helps, but I still have questions:
(1) If a is set to 0, why is d not set to 3, but 4?
(2) What is the difference between the number of letters used in the keys? For example, does using ‘ddddddddddddddddd’ vs. ‘dddd’ as keys produce different results? If yes, how?

Yes, the tests are helpful. More extremely, I can unlock the community solutions to find out the algorithm. But I feel like these are hacky ways to finish an exercise.
The instruction should lay out the exact algorithm the students are expected to follow. For starters, I think if the instruction explains how ‘aaaaaaaaaaaaaaaaaa’, ‘ddddddddddddddddd’ or ‘dddd’ are used in the encoding process, it would be greatly helpful

That’s a very good question :smile: I think a = 0 is base 0 offset and d = 4 is a base 4 offset, i.e. an error. Using a as the key shifts the input by 0 chars. Using d as the key shifts a -> d, b -> e.

No. They produce the same results. Offhand, I forget if the key needs to match the length of the input or if the key needs to be repeated to match the input length. Either the key matches the input length or the patterns d, ddd, dddddddd should all be equivalent. The tests should make that apparent.

The Python track on Exercism is explicitly and intentionally test driven. See the Test Driven Development doc. Exercism as a whole is pretty test driven. The tests are explicitly intended to be the source of truth for the exercise requirements. Reading and/or running the tests to understand the exercise is explicitly part of the intended workflow.

I looked for a = 0, d = 4. That’s not in the exercise. It was my post. I botched that shift by using different bases. Either a=1, d=4 or a=0, d=3.

No. They produce the same results. Offhand, I forget if the key needs to match the length of the input or if the key needs to be repeated to match the input length. Either the key matches the input length or the patterns d, ddd, dddddddd should all be equivalent. The tests should make that apparent.

Thank you for your help, but as it turns out this is only partially true. The keys do not have to be matched to the length of the input but are recycled to match the length of the input. More importantly, the keys are letter-for-letter mapped to the input to be encoded. The amount of shift for each letter is determined by the letter of the same position in the key. For example, if the input is ‘xxx’, and the key is ‘abc’. The algorithm would shift 0 (a=0) position for the first letter, 1 (b=1) position for the second letter, and 2 (c=2) position for the third letter, resulting in an output of ‘xyz’.

The above key algorithm details are grossly missing from the instructions. And they are very difficult to figure out by reserve-engineering the tests if not impossible. I would still hope the instructions to be more clear on the algorithm. After all, the students here are to practice their programming skills, not to solve the mystery of the instructions (my humble opinion).

Hello!

I am failing two tests, but I can’t understand why (unfortunately I am not able to interpret test code in test module… :pensive:

Can anybody please help me understand each one of these tests requirements?

________________________________ RandomKeyCipherTest.test_can_decode ________________________________

self = <simple_cipher_test.RandomKeyCipherTest testMethod=test_can_decode>

    def test_can_decode(self):
        cipher = Cipher()
>       self.assertEqual(cipher.decode(cipher.key[0 : len("aaaaaaaaaa")]), "aaaaaaaaaa")
E       TypeError: 'NoneType' object is not subscriptable

simple_cipher_test.py:19: TypeError
__________________ RandomKeyCipherTest.test_key_is_made_only_of_lowercase_letters ___________________

self = <simple_cipher_test.RandomKeyCipherTest testMethod=test_key_is_made_only_of_lowercase_letters>

    def test_key_is_made_only_of_lowercase_letters(self):
>       self.assertIsNotNone(re.match("^[a-z]+$", Cipher().key))

simple_cipher_test.py:27: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

pattern = '^[a-z]+$', string = None, flags = 0

    def match(pattern, string, flags=0):
        """Try to apply the pattern at the start of the string, returning
        a Match object, or None if no match was found."""
>       return _compile(pattern, flags).match(string)
E       TypeError: expected string or bytes-like object

/usr/lib/python3.10/re.py:190: TypeError

Kind regards,

Rod.

These tests instantiate a Cipher() object then test the value of the self.key attribute. Are you defining a self.key in the Ciper.__init__()? Are you setting it to a string value (and not None)?

Hello, Isaac! How are you today?

Thank you for helping me.

Yes, I set self.key = key in Cipher.__init__ ()

And inside “encode() method” there is a condition that if self.key is none, then a random key is generated and associated with self.key.

Even though I failed these two tests, I think asking for mentorship may be a good idea. What do you think?

Kind regards,

Rod.

self.key needs to be not-None by the time __init__() returns. Setting its value at a later time isn’t sufficient. The tests initialize the object and expect it to have a not-None value prior to calling anything else.

I encourage people to always ask for mentoring! At any stage. Sometimes even multiple times!

Hi everyone, I agree with @J-ZW-Wang that the instructions are suboptimally clear. I spent a long time yesterday staring at the tests and unable to figure out how the key is meant to signal the shift(s). Also, the Simple section on the Wikipedia page on Substitution Ciphers suggests a different usage of the key, which only fostered my misunderstanding. :smiley:

I would suggest to include one additional sentence after


Given the key “aaaaaaaaaaaaaaaaaa”, encoding the string “iamapandabear” would return the original “iamapandabear”.

Given the key “ddddddddddddddddd”, encoding our string “iamapandabear” would return the obscured “ldpdsdqgdehdu”


Namely, something like:

Given the key “abc”, encoding the string “aaaaaaab” would be result in “abcabcab”, so the nth character of the key determines the shift for characters in the string for which i modulo key_length = n, with i denoting the position of the character in the string.

Something in this direction would make the instructions much clearer and avoid unnecessary time spent deciphering them, which could be better spent solving the exercise.

Wdyt?

Cheers!

Should the instructions refer to Vigenère cipher instead of ‘Substitution cipher’ ?

These instructions are from problem specifications, not the Python track.

@iHiD – could we please move this thread to the general category for discussion?

1 Like

Moved to Building Exercism with the language tag removed.

3 Likes

That would seem to be the correct one, yes! :slight_smile: