'Vigenère Cipher function implementation

After watching this tutorial about the Vigenere Cipher, I (hopefully) understand its basic concepts. We want to assign a key to a string, and then shift each letter in the string by the (0-based) alphabet-position value of each letter in the key. So when using bacon as the key,

Meet me in the park at eleven am
baco nb ac onb acon ba conbac on

becomes

Negh zf av huf pcfx bt gzrwep oz

As I'm writing a Vigenere Cipher from scratch, I only know that the first step is to assign the key to a string. And while I'm doing this, I want to recognize whether or not each of the characters is alpha so that I can preserve any special characters in the string (!, @, #, etc.) if there are any.

text = input("Enter some text:")

def encrypt(text):

#key = bacon
encrypted = []
baconvalue = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3, 'd':3, 'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6, 'H':7, 'h':7, 'I':8, 'i':8, 'J':9, 'j':9, 'K':10, 'k':10, 'L':11, 'l':11, 'M':12, 'm':12, 'N': 13, 'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16, 'q':16, 'R':17, 'r':17, 'S':18, 's':18, 'T':19, 't':19, 'U':20, 'u':20, 'V':21, 'v':21, 'W':22, 'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25 }


for letter in text:

#assign 'bacon' to text to get rotation value for each character
#preserve alpha characters

        if letter.isalpha():  
      
#character in string rotates x amount according to the corresponding value of char in bacon
        
            encrypted.append(letter, baconvalue)        

        else:    
    
            encrypted.append(letter)            
    
        return ''.join(encrypted)

print(encrypt(text,))

But as you can see, I don't know where to start as far as how to assign bacon to the string. Am I at least on the right track?



Solution 1:[1]

Possibly my full implementation for deciphering a Vigenère cipher might help you and others (it uses the Friedman test method with auto-correlation) understanding the method.

You can find the code here: https://github.com/ferreirafabio/vigenere-py

Solution 2:[2]

So my code is quite long but works quite well. Hope it helps

def VigenereCiphre(line, key):
    isupper = True
    key = key.strip(' ')
    key = key.upper()
    k = list(key)
    print(k)
    returnLine = []
    i = 0
    for char in list(line):

        # Check if current character is symbol. If true append it to encrypted line
        if ord(char) < 65 or ord(char) > 122:
            returnLine.append(char)
        elif ord(char) > 90 and ord(char) < 97:
            returnLine.append(char)
        else:
            # Checks if letter is capital. If it's not, stores isupper to false and make it uppercase
            if ord(char) > 90:
                isupper = False
                char = char.upper()

            else:
                isupper = True

            # Checks if key's index isn't out of range, if it is, set it back to 0
            print(isupper)
            if i == len(k):
                i = 0

            # create new character based on it's value

            c = ord(char) + ord(k[i]) - 65
            if c > 90:
                c = c - 25

            if isupper == False:
                print(c)
                c = c + 32
                print(c)

            returnLine.append(chr(c))

            i += 1

    a = ''
    return a.join(returnLine)

Solution 3:[3]

# Without import libraries
# Keep it simple

alph = 'abcdefghijklmnopqrstuvwxyz'

def encrypt_letter(char, key):
    if char.isalpha():
        shift = alph.index(char) 
        shifted_alph = alph[shift:] + alph[:shift] # rotate
        result = shifted_alph[key]
    else:
        result = char
    return result

def calculate_shifts(letter):
    return alph.index(letter)

def encrypt_text(txt, keyword):
    txt = txt.lower()
    en_ls = list()

# # >>> Method 1 for padding
#     keyword_times_in_txt = (int(len(txt) / len(keyword))+1) # round up
#     txt_padding_with_keyword = (keyword * keyword_times_in_txt)
#     txt_padding_with_keyword = txt_padding_with_keyword[:len(txt)] # slice at length of txt
# # <<< Method 1 for padding

# >>> Method 2 for padding
    txt_padding_with_keyword = list()
    for i in range(len(txt)):
        len_keyword = len(keyword)
        txt_padding_with_keyword.append(keyword[i % len_keyword])
# <<< Method 2 for padding    
    
    for i in range(len(txt)):
        key = calculate_shifts(txt_padding_with_keyword[i])
        char = txt[i]
        en_letter = encrypt_letter(char, key)
        en_ls.append(en_letter)
        
    result = "".join(en_ls)
    
    print(f"Keyword                 : {keyword}")
    print(f"Text                    : {txt}")
    print(f"Padded text with keyword: {''.join(txt_padding_with_keyword)}")

    return result 

# in_txt = input("Which text should be encrypted?")
# in_keyword = input("Which keyword should be used?")

in_txt = "Python is Really Beautiful!"
in_keyword  = "Random"

in_txt = in_txt.lower()
in_keyword = in_keyword.lower()

print(f"Encrypted text          : {encrypt_text(in_txt, in_keyword)}")

# Output:
# Keyword                 : random
# Text                    : python is really beautiful!
# Padded text with keyword: randomrandomrandomrandomran
# Encrypted text          : gygkcz if fqrlyb nvahwwrll!

Solution 4:[4]

In your collector.on("collect", ...)'s callback, you take a parameter i, but use button.deferUpdate() in the body of the function. button is not defined, result in an error, and the interaction times out.

In addition, your message.channel.send(...).then(message) overwrites the original message variable, so your filter is actually looking for interactions from the bot itself.

To fix this, remove the unnecessary variable message from the .then():

message.channel.send({ embeds: [embed], components: [row] }).then(() => {
  // ...

Also, change the parameter's name from i to button:

collector.on("collect", async button => {
  button.deferUpdate();
  // ...
}

Another issue is that collector.on("end") is called within collector.on("collect"). This may be unintended, and you may want to move that outside of the collector.on("collect") callback function.

Solution 5:[5]

Note that you cecked the wrong value of the button id

use button.customId instead of button.id this is not a correct to check the id.

Also on your collector there is so many resource embed create , practicaly this is a bad idea considering using one function to handle that win and lose :)

for making collector recognized what the component you been using you need to declare the type of components.

Like this.

const collector = message.createMessageComponentCollector({
 filter: ifilter,
 componenType: "BUTTON",
 time: 30000
})

Its seem your collector did not recognized your component.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 whiletrue
Solution 2 Jan Zajc
Solution 3
Solution 4
Solution 5 Agiel