Caesar cipher
Write caesar(s, k) that shifts every English letter k places along the alphabet, wrapping from z back to a. Keep upper and lower case, and leave everything else unchanged. k may be negative.
caesar("Hello, World!", 3) # "Khoor, Zruog!"
caesar("abc", -1) # "zab"
Show hint
ord("a") is 97 and chr(97) is "a". Convert each letter to a number from 0 to 25, add k, and use % 26 to wrap.
Show solution
def caesar(s, k):
out = []
for ch in s:
if ch.isascii() and ch.isalpha():
base = ord("A") if ch.isupper() else ord("a")
out.append(chr((ord(ch) - base + k) % 26 + base))
else:
out.append(ch)
return "".join(out)
Subtracting base maps a letter to 0 to 25, and % 26 wraps it, even for negative shifts, because Python's % always returns a non-negative result here. Decoding is just caesar(s, -k).
Do not use this to protect anything: there are only 26 possible keys, so trying them all takes a computer no time.
Want a problem like this every day? See today's problem and keep a streak going.