# Playground for https://stackoverflow.com/a/56143306/11458991
import string
def letter_index(letter):
"""Determines the position of the given letter in the English alphabet
'a' -> 0
'A' -> 0
'z' -> 25
"""
if letter not in string.ascii_letters:
raise ValueError("The argument must be an English letter")
if letter in string.ascii_lowercase:
return ord(letter) - ord('a')
return ord(letter) - ord('A')
def caesar(s):
"""Ciphers the string s by shifting 'A'->'B', 'B'->'D', 'C'->'E', etc
The shift is cyclic, i.e. 'A' comes after 'Z'.
"""
ret = ""
for letter in s:
index = letter_index(letter)
new_index = 2*index + 1
if new_index >= len(string.ascii_lowercase):
# The letter is shifted farther than 'Z'
new_index %= len(string.ascii_lowercase)
new_letter = chr(ord(letter) - index + new_index)
ret += new_letter
return ret
print('caesar("ABC"):', caesar("ABC"))
print('caesar("abc"):', caesar("abc"))
print('caesar("XYZ"):', caesar("XYZ"))
IyBQbGF5Z3JvdW5kIGZvciBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNTYxNDMzMDYvMTE0NTg5OTEKCgppbXBvcnQgc3RyaW5nCgoKZGVmIGxldHRlcl9pbmRleChsZXR0ZXIpOgoJIiIiRGV0ZXJtaW5lcyB0aGUgcG9zaXRpb24gb2YgdGhlIGdpdmVuIGxldHRlciBpbiB0aGUgRW5nbGlzaCBhbHBoYWJldAoJCgknYScgLT4gMAoJJ0EnIC0+IDAKCSd6JyAtPiAyNQoJIiIiCglpZiBsZXR0ZXIgbm90IGluIHN0cmluZy5hc2NpaV9sZXR0ZXJzOgoJCXJhaXNlIFZhbHVlRXJyb3IoIlRoZSBhcmd1bWVudCBtdXN0IGJlIGFuIEVuZ2xpc2ggbGV0dGVyIikKCQoJaWYgbGV0dGVyIGluIHN0cmluZy5hc2NpaV9sb3dlcmNhc2U6CgkJcmV0dXJuIG9yZChsZXR0ZXIpIC0gb3JkKCdhJykKCXJldHVybiBvcmQobGV0dGVyKSAtIG9yZCgnQScpCgoKZGVmIGNhZXNhcihzKToKCSIiIkNpcGhlcnMgdGhlIHN0cmluZyBzIGJ5IHNoaWZ0aW5nICdBJy0+J0InLCAnQictPidEJywgJ0MnLT4nRScsIGV0YwoJCglUaGUgc2hpZnQgaXMgY3ljbGljLCBpLmUuICdBJyBjb21lcyBhZnRlciAnWicuCgkiIiIKCXJldCA9ICIiCglmb3IgbGV0dGVyIGluIHM6CgkJaW5kZXggPSBsZXR0ZXJfaW5kZXgobGV0dGVyKQoJCW5ld19pbmRleCA9IDIqaW5kZXggKyAxCgkJaWYgbmV3X2luZGV4ID49IGxlbihzdHJpbmcuYXNjaWlfbG93ZXJjYXNlKToKCQkJIyBUaGUgbGV0dGVyIGlzIHNoaWZ0ZWQgZmFydGhlciB0aGFuICdaJwoJCQluZXdfaW5kZXggJT0gbGVuKHN0cmluZy5hc2NpaV9sb3dlcmNhc2UpCgkJbmV3X2xldHRlciA9IGNocihvcmQobGV0dGVyKSAtIGluZGV4ICsgbmV3X2luZGV4KQoJCXJldCArPSBuZXdfbGV0dGVyCgkKCXJldHVybiByZXQKCgpwcmludCgnY2Flc2FyKCJBQkMiKTonLCBjYWVzYXIoIkFCQyIpKQpwcmludCgnY2Flc2FyKCJhYmMiKTonLCBjYWVzYXIoImFiYyIpKQpwcmludCgnY2Flc2FyKCJYWVoiKTonLCBjYWVzYXIoIlhZWiIpKQ==