Python problem 19 of 30

Caesar cipher

  • Python
  • Medium

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.