diff --git a/workshop1/README.md b/workshop1/README.md new file mode 100644 index 0000000..e1b1364 --- /dev/null +++ b/workshop1/README.md @@ -0,0 +1,105 @@ +# Workshop 1 - Конзолно приложение за шифриране/дешифриране +*Преди да започнем, учтиво искаме да ви помолим да **изключите** копилоти, ако използвате такива при писане на код, както и да **не използвате** чат асистенти.* + +*Не възнаграждаваме с точки за успешно решение - целта е сами да се пробвате да помислите и напишете кода на програмата, за да има максимална полза за вас.* + +## Backstory + +[Цезаровият шифър](https://bg.wikipedia.org/wiki/%D0%A6%D0%B5%D0%B7%D0%B0%D1%80%D0%BE%D0%B2_%D1%88%D0%B8%D1%84%D1%8A%D1%80) е един от най-старите и най-прости методи за криптиране на текст. Той се основава на заместване на всяка буква в текста с друга буква, която се намира на фиксиран брой позиции по-надясно (при криптиране) или по-наляво (при декриптиране) в дадена азбука. + +**"Ключ"** (key) наричаме този фиксиран брой позиции. Например, ако използваме ключ 3 с английската азбука при криптиране, буквата 'A' ще бъде заменена с 'D', буквата 'B' с 'E', и така нататък. +* Ако стигнем до края на азбуката, продължаваме от началото (т.е. 'Z' с ключ 3 става 'C'). +* Ако някой символ не е от азбуката (пунктуация, цифри, чужди букви, т.н.), той остава непроменен. + +## Функционалности +Вашата задача е да довършите файла `cipher.py` по такъв начин, че да може да бъде изпълняван от командния ред (дадена ви е помощна имплементация за това с `argparse`), като поддържа следния синтаксис и функционалности: + +```shell +python cipher.py [] -k [-a ] +``` + +където: +* `` е или `encrypt`, или `decrypt`. Указва в коя посока да се извърши трансформацията. + * При `encrypt` всяка буква се измества с ключа надясно (прибавя се стойността на ключа към поредността на буквата). + * При `decrypt` всяка буква се измества с ключа наляво (изважда се стойността на ключа от поредността на буквата). + * Запазва се вида на буквите (главни/малки). + * Символи извън указаната азбука не се променят (букви от чужда азбука, цифри, пунктуация, др. символи). +* `` е текстов низ (str), който може да съдържа букви, цифри, пунктуация и други символи. Той трябва да бъде обработен според зададения режим и ключ. + * Този аргумент може да бъде пропуснат. В такъв случай програмата трябва да изчака вход от потребителя (чрез вградената функция `input()`), за да получи текста за обработка. +* `-k ` е цяло число, което указва ключът. Валидни стойности са от 1 до дължината на азбуката минус едно. + * Да се изведе подходяща грешка при невалиден ключ. + * Специално за ключ 0 или ключ равен на дължината на азбуката, да се изведе съобщение `Key results in no change.` и програмата да приключи без да прави нищо останало. +* `-a ` е аргумент по желание, който указва коя азбука да се използва. Ако не е подаден, по подразбиране се използва `en` - английската азбука (A-Z с 26 букви). Възможни стойности: + * `en`: английска (`ABCDEFGHIJKLMNOPQRSTUVWXYZ`) + * `bg`: българска (`АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯ`) + * `ru`: руска (`АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ`) + * `de`: немска (`ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜß`) + * `tr`: турска (`ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ`) + * `gr`: гръцка (`ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ`) + * ... (можете да добавите и други азбуки по ваше желание) + * Потребителят може да подаде само едно име на азбука. + * Потребителят трябва да може да подаде името на азбуката с малки букви, главни букви или смесено. + * При подаване на име на азбука, която не е от изброените горе, да се изведе съобщение `Unrecognized alphabet {alphabet_name}. Supported values are: {list_of_supported_alphabets}` и програмата да приключи. В съобщението `{alphabet_name}` се замества с подаденото от потребителя име, а в `{list_of_supported_alphabets}` се изреждат всички поддържани азбуки, разделени със запетая и интервал. + * Пример: `Unrecognized alphabet foo. Supported values are: en, bg, ru, de, tr, gr`. + +## Примери + +```shell +$ python cipher.py encrypt xyzabc -k 3 + +abcdef +``` + +```shell +$ python cipher.py encrypt "Hello, world!" -k 3 + +Khoor, zruog! +``` + +```shell +$ python cipher.py decrypt "Khoor, zruog!" -k 3 + +Hello, world! +``` + +```shell +$ python cipher.py encrypt -k 16 +Here the program waits for the user to input text +Xuhu jxu fhewhqc mqyji veh jxu kiuh je ydfkj junj +``` + +```shell +$ python cipher.py encrypt "Я виж, можем и на български." -k 2 -a bg + +Б дки, оризо к пв гюневтумк. +``` + +```shell +$ python cipher.py encrypt "Я виж, можем и на български." -k 2 + +Я виж, можем и на български. +``` + +```shell +$ python cipher.py encrypt whatever -k 666 + +Invalid key 666. Key must be between 1 and 25. +``` + +```shell +$ python cipher.py encrypt whatever -k 0 + +Key results in no change. +``` + +```shell +$ python cipher.py encrypt whatever -k 3 -a foo + +Unrecognized alphabet foo. Supported values are: en, bg, ru, de, tr, gr. +``` + +## Помощ +* За намиране на индекс на символ (или substring) в низ, може да използвате [str.find()](https://docs.python.org/3/library/stdtypes.html#str.find). +* За проверка дали даден символ е главна буква, може да използвате `str.isupper()`. +* За преждевременен изход от програмата, може да използвате `sys.exit()`. +* Може да проверите дали работи коректно програмата ви с някой специализиран за това сайт, например този: https://cryptii.com/pipes/caesar-cipher \ No newline at end of file diff --git a/workshop1/cipher.py b/workshop1/cipher.py new file mode 100644 index 0000000..fec3320 --- /dev/null +++ b/workshop1/cipher.py @@ -0,0 +1,20 @@ +import argparse + + +parser = argparse.ArgumentParser() +parser.add_argument("mode", choices=["encrypt", "decrypt"], help="Mode of operation (encrypt or decrypt)") +parser.add_argument("text", nargs="?", help="Text to be processed") +parser.add_argument("-k", "--key", type=int, required=True, help="Key for encryption/decryption") +parser.add_argument("-a", "--alphabet", default="en", help="Alphabet to use") +args = parser.parse_args() + +mode = args.mode +text = args.text +key = args.key +alphabet = args.alphabet + +# print(f"Helpful debug info: {mode=}, {key=}, {alphabet=}, {text=}") + + +# свободни сте да пишете и променяте кода във файла както сметнете за най-удачно +# употребата на функции е препоръчителна