0

This is the first time i'm asking problems as i'm a noob in programming.

I'm trying to complete problems from Codewars,

"ROT13 is a simple letter substitution cipher that replaces a letter with the letter 13 letters after it in the alphabet. ROT13 is an example of the Caesar cipher.

Create a function that takes a string and returns the string ciphered with Rot13. If there are numbers or special characters included in the string, they should be returned as they are. Only letters from the latin/english alphabet should be shifted, like in the original Rot13 "implementation"."

I've tried to code it at my best abilities, and it come up like this.

def rot13(message):
    v = []
    for i in message:
        if i.isupper()== True:
            d = ord(i) + 13
            e = chr(d)
            if d > 90:
                u = (d - 91)
                o = chr(u+65)
                v.append(o)
            else:
                v.append(e)
        elif i.islower() == True:
            x = (ord(i)+13)
            y = chr(x)
        
            if x > 122:
                z = (x - 123)
                p = chr(z+97)
                v.append(p)
            
            else:
                v.append(y)
        else:
            v.append(i)

    print(''.join(v))
        

It worked (seemingly), but it says that it's not correct. Where does it wrong ? I know it's ugly, but well. Thank you in advance.

  • 1
    You might also want to look at [`str.translate`](https://docs.python.org/3/library/stdtypes.html#str.translate)... hint: for a weird rot-1, you'd do: `'cabbage'.translate(str.maketrans('abc', 'bca'))` which'll return `abccbge`... and you can go from there... – Jon Clements May 28 '21 at 10:47
  • 1
    And in this case one can use the predefined values `ascii_lowercase` and `ascii_uppercase` from the `str` module to construct the parameters for `maketrans`. This could be `source = ascii_lowercase + ascii_uppercase` and `target = ascii_lowercase[13:] + ascii_lowercase[:13] + ascii_uppercase[13:] + ascii_uppercase[:13])` – Matthias May 28 '21 at 10:58

1 Answers1

0

If I'm not mistaken, you're referring to https://www.codewars.com/kata/530e15517bc88ac656000716. Note what the test case does:

test.assert_equals(rot13("test"),"grfg")
test.assert_equals(rot13("Test"),"Grfg")

They don't want you to print the result, they want you to return it. This matches the task, which says

Create a function that takes a string and returns the string ciphered with Rot13

If you simply change the last line from

print(''.join(v))

to

return ''.join(v)

it passes the test.

There are some other questions that go into detail about the differences between printing and returning, for example this one

Edit: Note that your algorithm so far is correct, but only when you assume your input only includes ascii characters. For non-ascii characters, you might not want to rotate them, but they could be identified as being lower or upper case by python. One example would be the German umlauts "ä", "ö" and "ü". For these cases, Matthias and Jon have provided ideas (that also allow a more elegant implementation). Also, you could check out other submissions on Codewars and see how other people did it.

He3lixxx
  • 3,263
  • 1
  • 12
  • 31
  • This still misses the "english alphabet" part. If you call `rot13('Motörhead')` the `ö` should be unchanged. – Matthias May 28 '21 at 10:50
  • That is true and it would be an issue if the input was specified to be arbitrary utf-8. The challenge does not specify any input encoding. Since it is a coding challenge, and it passes all tests with this assumption, I think it's fair to assume our input is ascii-7 encoded. – He3lixxx May 28 '21 at 11:00