From 017b35be9f77b8afb690505621d9cd958be177ba Mon Sep 17 00:00:00 2001 From: Aleksandar Date: Sat, 18 Oct 2025 17:08:01 +0300 Subject: [PATCH 1/3] Workshop 1 readme + public template --- workshop1/README.md | 95 +++++++++++++++++++++++++++++++++++++++++++++ workshop1/cipher.py | 20 ++++++++++ 2 files changed, 115 insertions(+) create mode 100644 workshop1/README.md create mode 100644 workshop1/cipher.py diff --git a/workshop1/README.md b/workshop1/README.md new file mode 100644 index 0000000..4b70a41 --- /dev/null +++ b/workshop1/README.md @@ -0,0 +1,95 @@ +# 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 ] +``` + +където: +* `MODE` е или `encrypt`, или `decrypt`. Указва в коя посока да се извърши трансформацията. + * При `encrypt` всяка буква се измества с ключа надясно (прибавя се стойността на ключа към поредността на буквата). + * При `decrypt` всяка буква се измества с ключа наляво (изважда се стойността на ключа от поредността на буквата). + * Запазва се вида на буквите (главни/малки). + * Символи извън указаната азбука не се променят (букви от чужда азбука, цифри, пунктуация, др. символи). +* `` е текстов низ (str), който може да съдържа букви, цифри, пунктуация и други символи. Той трябва да бъде обработен според зададения режим и ключ. +* `-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 hello -k 3 + +khoor +``` + +```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 5 -a bg + +Б дки, оризо к пв гюневтумк. +``` + +```shell +$ python cipher.py encrypt "Я виж, можем и на български." -k 5 + +Я виж, можем и на български. +``` + +```shell +$ python cipher.py encrypt whatever -k 666 + +Invalid key. 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. +``` + +## Полезни линкове +Може да проверите дали работи коректно програмата ви с някой специализиран за това сайт, например този: 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..13680b9 --- /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", 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=}") + + +# свободни сте да пишете и променяте кода във файла както сметнете за най-удачно +# употребата на функции е препоръчителна From d4df73ad6be6be4fdd876977a3436735667f8862 Mon Sep 17 00:00:00 2001 From: Aleksandar Date: Sat, 18 Oct 2025 17:48:08 +0300 Subject: [PATCH 2/3] Add case, fix examples --- workshop1/README.md | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/workshop1/README.md b/workshop1/README.md index 4b70a41..e1b1364 100644 --- a/workshop1/README.md +++ b/workshop1/README.md @@ -15,16 +15,17 @@ Вашата задача е да довършите файла `cipher.py` по такъв начин, че да може да бъде изпълняван от командния ред (дадена ви е помощна имплементация за това с `argparse`), като поддържа следния синтаксис и функционалности: ```shell -python cipher.py -k [-a ] +python cipher.py [] -k [-a ] ``` където: -* `MODE` е или `encrypt`, или `decrypt`. Указва в коя посока да се извърши трансформацията. +* `` е или `encrypt`, или `decrypt`. Указва в коя посока да се извърши трансформацията. * При `encrypt` всяка буква се измества с ключа надясно (прибавя се стойността на ключа към поредността на буквата). * При `decrypt` всяка буква се измества с ключа наляво (изважда се стойността на ключа от поредността на буквата). * Запазва се вида на буквите (главни/малки). * Символи извън указаната азбука не се променят (букви от чужда азбука, цифри, пунктуация, др. символи). * `` е текстов низ (str), който може да съдържа букви, цифри, пунктуация и други символи. Той трябва да бъде обработен според зададения режим и ключ. + * Този аргумент може да бъде пропуснат. В такъв случай програмата трябва да изчака вход от потребителя (чрез вградената функция `input()`), за да получи текста за обработка. * `-k ` е цяло число, което указва ключът. Валидни стойности са от 1 до дължината на азбуката минус едно. * Да се изведе подходяща грешка при невалиден ключ. * Специално за ключ 0 или ключ равен на дължината на азбуката, да се изведе съобщение `Key results in no change.` и програмата да приключи без да прави нищо останало. @@ -44,9 +45,9 @@ python cipher.py -k [-a ] ## Примери ```shell -$ python cipher.py encrypt hello -k 3 +$ python cipher.py encrypt xyzabc -k 3 -khoor +abcdef ``` ```shell @@ -62,13 +63,19 @@ Hello, world! ``` ```shell -$ python cipher.py encrypt "Я виж, можем и на български." -k 5 -a bg +$ 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 5 +$ python cipher.py encrypt "Я виж, можем и на български." -k 2 Я виж, можем и на български. ``` @@ -76,7 +83,7 @@ $ python cipher.py encrypt "Я виж, можем и на български." - ```shell $ python cipher.py encrypt whatever -k 666 -Invalid key. Key must be between 1 and 25. +Invalid key 666. Key must be between 1 and 25. ``` ```shell @@ -91,5 +98,8 @@ $ python cipher.py encrypt whatever -k 3 -a foo Unrecognized alphabet foo. Supported values are: en, bg, ru, de, tr, gr. ``` -## Полезни линкове -Може да проверите дали работи коректно програмата ви с някой специализиран за това сайт, например този: https://cryptii.com/pipes/caesar-cipher \ No newline at end of file +## Помощ +* За намиране на индекс на символ (или 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 From e192540031c7eaeaf7eb2b5b439fee1114ff01a4 Mon Sep 17 00:00:00 2001 From: Aleksandar Date: Sat, 18 Oct 2025 17:53:53 +0300 Subject: [PATCH 3/3] Fix text input --- workshop1/cipher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workshop1/cipher.py b/workshop1/cipher.py index 13680b9..fec3320 100644 --- a/workshop1/cipher.py +++ b/workshop1/cipher.py @@ -3,7 +3,7 @@ parser = argparse.ArgumentParser() parser.add_argument("mode", choices=["encrypt", "decrypt"], help="Mode of operation (encrypt or decrypt)") -parser.add_argument("text", help="Text to be processed") +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()