1

As part of the CS50 Harvard programming course, which I'm currently attending, I'm doing an exercise called "Vigenere".

The Cipher of Vigenere is supposed to have a key as input, for example "abcd". This will encode any plaintext, according to each character in the key, where a = 0 and b = 1 etc. So a key "abcd" with plaintext "aa!aa" would give "ab!cd". if the plaintext is longer than the key, the key is supposed to loop back to [0] and start over until plaintext has all been encoded. Non alphabetic letters are supposed to printed out normally however.

My program is doing everything right (it's going line by line and the expected behavior is met) except when I receive input that starts with an uppercase letter followed by a lowercase letter my program prints a different letter with the lowercase key then it should give me. EX: key: "Baz". Plaintext: "aaa". Result: "bgz" where it should return "baz".

Have been googling, debugging but just can't figure it out. Have tried doing it in a lot of other different ways too but I just can't get it to work. (sorry for kind of copy paste, as you might notice I've already posted a similar problem, however that was in C (this is python) and it was a different kind of bug)

Code:

import sys

if len(sys.argv) != 2 or not sys.argv[1].isalpha():
    print("usage: python vigenere.py keyword")
    sys.exit()

cipher = sys.argv[1]
plaintext = input("plaintext: ")

j = 0

def code(j):
    for key in cipher:
        if key.islower():
            return ord(cipher[j]) - 97
        if key.isupper():
            return ord(cipher[j]) - 65

print("ciphertext: ", end="")

for letters in plaintext:
    if letters.islower():
        print(chr(((ord(letters) - 97 + code(j)) % 26) + 97), end="")
        j += 1
    if letters.isupper():
        print(chr(((ord(letters) - 65 + code(j)) % 26) + 65), end="")
        j += 1
    if j == len(cipher):
        j = 0
    if not letters.isalpha():
        print(letters, end="")

print("")
Enthus3d
  • 1,727
  • 12
  • 26
AltijdGoed
  • 55
  • 6
  • Welcome to StackOverflow. Please read and follow the posting guidelines in the help documentation, as suggested when you created this account. [Minimal, complete, verifiable example](https://stackoverflow.com/help/minimal-reproducible-example) applies here. We cannot effectively help you until you post your MCVE code and accurately specify the problem. We should be able to paste your posted code into a text file and reproduce the problem you specified. Your post requires external input and a foreign module; we expect it to be self-contained. – Prune Oct 02 '19 at 17:27
  • 3
    You also neglected to demonstrate the problem: "my program bugs out" is not an error specification. – Prune Oct 02 '19 at 17:27
  • 1
    Welcome to SO. Try to make any question you post reproducible to anyone that comes along. You have a custom library (cs50) for a specific college class that I'm guessing a very small number of people already have. The function you import *looks* basic enough for you to implement yourself, (replace get_string with input????) – SyntaxVoid Oct 02 '19 at 17:27
  • @SyntaxVoid ok sorry guys I edited the post you should be able to copy paste it rn – AltijdGoed Oct 02 '19 at 17:33
  • can you be more specific about the bug, other than "bugs out"? What is wrong? what output did you expect and what did you actually get? – Yakov Dan Oct 02 '19 at 17:37
  • @Prune yeah sorry changed it now – AltijdGoed Oct 02 '19 at 17:37
  • @YakovDan changed it! basically with a key that has an uppercase letter followed by a lowercase letter it prints out the wrong letter. EX: key: "Lap". Plaintext: "aaa". Result: "lgp" where it should return "lap" – AltijdGoed Oct 02 '19 at 17:39
  • @AltijdGoed. if you key is "Lap" and your plain text is "aaa", shouldn't the correct return value be "Lap" and not "lap"? – Yakov Dan Oct 02 '19 at 17:45
  • @YakovDan uppercase letters in the key should encode the same as lowercase letters, only if its an uppercase letter in the plaintext it should be printed as an uppercase – AltijdGoed Oct 02 '19 at 17:54

1 Answers1

1

The problem in your code is caused by your code function.

In it, you use the line for key in cipher:, before checking it with if key.islower(): or if key.isupper():.

The problem is that every time we enter the code function, due to the for loop we only check if the first letter in the cipher is upper or lower case.

eg. for cipher 'Baz', j = 0, we check if B is upper/lower, and get upper. We immediately return uppercase B

For cipher 'Baz', j = 1, we check if B is upper/lower, and get upper. We immediately return upper A. (When we should be checking a for upper/lower, and returning lower a!)


This problem is fixed by checking the right letter of the cipher for upper or lower case, and can be fixed by replacing for key in cipher: with key = cipher[j], like in the block below:

def code(j):
    key = cipher[j]
    if key.islower():
        return ord(key) - 97
    if key.isupper():
        return ord(key) - 65

After making the change, for the following inputs:

cipher = "BazBgh" plaintext = "aaaaAa"

We get

ciphertext: bazbGh

Community
  • 1
  • 1
Enthus3d
  • 1,727
  • 12
  • 26
  • You're awesome! thanks so much man! Apologies to everyone on SO for creating this post without providing correct code (wasnt copy pastable at first due to custom function) but have taken notice of the rules and will abide by them. Thanks again – AltijdGoed Oct 02 '19 at 18:06
  • Oh, np @AltijdGoed. Glad that I could help. It's the attitude that counts, don't be discouraged by initial reactions. I personally found your question to be well-edited enough to help answer it, so making your questions well-explained and providing enough examples will help you through without issue. Good luck! – Enthus3d Oct 02 '19 at 18:08
  • By the way @AltijdGoed, don’t forget to accept an answer if it helped solve your issue; this basically lets others see that your question has been resolved in the question feed. – Enthus3d Oct 02 '19 at 18:33