srkdb
srkdb

Reputation: 815

Single character mismatch in Caesar Cipher: Python

Essentially, the alphabets in the input string are cyclically rotated by k and the rest of the characters retains their form. I'm puzzled by a mismatch. For my code:

import math
import os
import random
import re
import sys

# Complete the caesarCipher function below.
def caesarCipher(s, k):
    st = []
    for i in range(0,len(s)):
        if 65<=ord(s[i])<=90: 
            temp = ord(s[i])+k
            if (temp>90):
                temp-=26
            st.append(chr(temp))
        elif 97<=ord(s[i])<=122:
            temp = ord(s[i])+k
            if (temp>122):
                temp-=26
            st.append(chr(temp))   
        else: st.append(s[i])
    return ''.join(st)




if __name__ == '__main__':

    s = input()

    k = int(input())

    result = caesarCipher(s, k)

The output always fails by one, like My: okffng-Qwvc Expected: okffng-Qwvb

My:Fqcfex-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj Expected: Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj

I can't seem to detect the bug.

Upvotes: 1

Views: 193

Answers (1)

Hans Musgrave
Hans Musgrave

Reputation: 7111

The typical presentation of a Caesar Cipher uses a modulus operator. I'd probably start there in debugging your code.

I find code easier to debug if it is flat rather than nested. If each function does one small thing, it's easier to completely test that one small function and fit them together to have the correct behavior. Take the following example:

def _caesarLetter(c, k, offset):
    return chr((ord(c)-offset+k)%26+offset)

def caesarLetter(c, k):
    if not c.alpha():
        return c
    return _caesarLetter(c, k, ord('a') if c.islower() else ord('A'))

def caesarCipher(s, k):
    return ''.join(caesarLetter(c, k) for c in s)
  • The first method _caesarLetter applies the cipher to a single letter, and only for a fixed character encoding. It basically takes the whole alphabet and translates it to start at 0, it applies the cipher, and it moves the alphabet back to where it started. For lowercase ascii this is at 97, and for uppercase it is at 65.

  • The second method caesarLetter takes care of figuring out where lowercase and uppercase alphabets start in the ascii encoding. Rather than explicitly encoding 65 and 97, which is prone to typos and unclear errors, we just compute them on the fly. CPU time is cheap. Developer time is expensive. This makes the intent clear.

  • The third method caesarCipher just does that for all the letters in your string and joins them together.

Upvotes: 2

Related Questions