diff --git a/ciphers/gronsfeld_cipher.py b/ciphers/gronsfeld_cipher.py new file mode 100644 index 000000000..8fbeab430 --- /dev/null +++ b/ciphers/gronsfeld_cipher.py @@ -0,0 +1,45 @@ +from string import ascii_uppercase + + +def gronsfeld(text: str, key: str) -> str: + """ + Encrypt plaintext with the Gronsfeld cipher + + >>> gronsfeld('hello', '412') + 'LFNPP' + >>> gronsfeld('hello', '123') + 'IGOMQ' + >>> gronsfeld('', '123') + '' + >>> gronsfeld('yes, ¥€$ - _!@#%?', '0') + 'YES, ¥€$ - _!@#%?' + >>> gronsfeld('yes, ¥€$ - _!@#%?', '01') + 'YFS, ¥€$ - _!@#%?' + >>> gronsfeld('yes, ¥€$ - _!@#%?', '012') + 'YFU, ¥€$ - _!@#%?' + >>> gronsfeld('yes, ¥€$ - _!@#%?', '') + Traceback (most recent call last): + ... + ZeroDivisionError: integer modulo by zero + """ + ascii_len = len(ascii_uppercase) + key_len = len(key) + encrypted_text = "" + keys = [int(char) for char in key] + upper_case_text = text.upper() + + for i, char in enumerate(upper_case_text): + if char in ascii_uppercase: + new_position = (ascii_uppercase.index(char) + keys[i % key_len]) % ascii_len + shifted_letter = ascii_uppercase[new_position] + encrypted_text += shifted_letter + else: + encrypted_text += char + + return encrypted_text + + +if __name__ == "__main__": + from doctest import testmod + + testmod()