Раздел «Язык Си».PythonCodes:

Источники по простым шрифтам:

Главное

Из числа 3 получить букву d

#      0123456789...
eng = 'abcdefghijklmnopqrstuvwxyz'
c = eng[3]
print(c)      # d

Из буквы d получить число 3

eng = 'abcdefghijklmnopqrstuvwxyz'
k = eng.find('d')
print(k)      # 3

Проверить, что буква входит в строку (то же самое - элемент принадлежит последовательности)

if 'e' in 'hello':
    print('hello has e')
else:
    print('No e in hello')

Повторяем теорию: работа со строками и символами

string.ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'

string.ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

str.find(substr) - ищет в строке str первое вхождение подстроки substr и возвращает индекс начала подстроки. Если не находит, возвращает -1.

>>> a = list('Hello')
>>> print(a)
['H', 'e', 'l', 'l', 'o']
>>> s = '-'.join(a)
>>> s
'H-e-l-l-o'
>>> 'Hello'.find('el')    # на каком месте начинается строка
1
>>> 'Hello'.find('l')     # первое вхождение слева
2
>>> 'Hello'.find('zzz')   # не нашли
-1
>>> ord('a')
97
>>> chr(97)
'a'
>>> 'HElLo, WoRlD'.lower()
'hello, world'
>>> 'HElLo, WoRlD'.upper()
'HELLO, WORLD'

Slice - часть строки или списка [от:до] или [от:до:шаг]

>>> s = 'Hello!'
>>> s[1:4]
'ell'
>>> s[2:]
'llo!'
>>> s[:2]
'He'
>>> s[1:5:2]
'el'
>>> s[0:5:2]
'Hlo'
>>> s[::2]
'Hlo'
>>> s[::-2]
'!le'
>>> s[::-1]
'!olleH'

Перебираем с индексами:

for i, c in enumerate('hello'):
    print(i, c)
# получим
# 0 h
# 1 e
# 2 l
# 3 l
# 4 o

Повторяем списки

Шифры

Переписку могут перехватывать. Чтобы письма не могли читать другие люди, их шифровали.

Шифр Цезаря

Очень старый шифр. Алфавит сдвигается на N букв и получается зашифрованный алфавит. Cдвинем на 3 буквы, получим:

abcdefghijklmnopqrstuvwxyz - что было
defghijklmnopqrstuvwxyzabc - зашифрованный алфавит

Зашифруем текст, заменяя букву а на d, b на e, с на f и так далее.

Строка 'hello' превратится в 'khoor'.

Задача 1.

Написать одному человеку кодирование (шифрование), а другому - декодирование (расшифровку).

Шифрование:

Input Output
3
hello
khoor
3
hello, world!
khoor, zruog!

Расшифровка:

Input Output
-3
khoor
hello
-3
khoor, zruog!
hello, world!

n = int(input())
text = input()
text = text.lower()  # все буквы маленькие

oldalphabet = 'abcdefghijklmnopqrstuvwxyz'
# или можно написать так:
# oldalphabet = string.ascii_lowercase 

def make_alphabet(oldalphabet, n):
    """ 
    из алфавита oldalphabet делает новый алфавит, сдвигая его на n букв.
    Возвращает новый алфавит 
    """
    # тут нужно написать код

def code_subst(oldalphabet, newalphabet, text):
    """ 
    Шифрует подстановками text из алфавита oldalphabet в алфавит newalphabet.
    Возвращает зашифрованный текст 
    """
    # тут нужно написать код

newalphabet = make_alphabet(oldalphabet, n)
codetext = code_subst(oldalphabet, newalphabet, text)
print(codetext)

Задача 2. Взлом шифра

Вы знаете, что фраза зашифрована кодом цезаря с неизвестным сдвигом. Попробуйте все возможные сдвиги и расшифруйте фразу.

Номер варианта дает преподаватель

1 zcysrgdsj gq zcrrcp rfyl sejw.
2 ibtpmgmx mw fixxiv xler mqtpmgmx.
3 rhlokd hr adssdq sgzm bnlokdw.
4 tfdgcvo zj svkkvi kyre tfdgcztrkvu.
5 xdsl ak twllwj lzsf fwklwv.
6 wtevwi mw fixxiv xler hirwi.
7 cplolmtwtej nzfyed.
8 qncagyj ayqcq ypcl'r qncagyj clmsef rm zpcyi rfc psjcq.
9 itbpwcop xzikbqkitqbg jmiba xczqbg.
10 uhhehi ixekbt duluh fqii iybudjbo.
11 sljcqq cvnjgagrjw qgjclacb.
12 sx dro pkmo yp kwlsqesdi, bopeco dro dowzdkdsyx dy qeocc.
13 lzwjw kzgmdv tw gfw-- sfv hjwxwjstdq gfdq gfw --gtnagmk osq lg vg al.
14 grznuamn zngz cge sge tuz hk uhbouay gz loxyz atrkyy eua'xk jazin.
15 dem yi rujjuh jxqd duluh.
16 fqymtzlm sjajw nx tkyjs gjyyjw ymfs *wnlmy* stb.
17 fc qeb fjmibjbkqxqflk fp exoa ql bumixfk, fq'p x yxa fabx.
18 xu iwt xbeatbtcipixdc xh tphn id tmeapxc, xi bpn qt p vdds xstp.
19 zmyqebmoqe mdq azq tazwuzs sdqmf upqm — xqf'e pa yadq ar ftaeq!

Еще повторим теорию про списки

>>> a = [3, 5, 17, -1]
>>> a
[3, 5, 17, -1]
>>> type(a)
<class 'list'>
>>> a.append(23)
>>> a
[3, 5, 17, -1, 23]
>>> a.extend([6, 88])
>>> a
[3, 5, 17, -1, 23, 6, 88]
>>> 4 in a
False
>>> 17 in a
True

Строки имеют со списками много общего:

>>> b = 'hello'
>>> b = b + 'abc'
>>> b
'helloabc'
>>> b += 'zzz'
>>> b
'helloabczzz'
>>> 'hi'*3
'hihihi'

Шифр Цезаря с изменением алфавита

Чтобы шифр было труднее взломать, новый алфавит делается с ключевой фразой.

Буквы из ключевой фразы берутся по 1 разу, остальные буквы берутся из алфавита.

abcdefghijklmnopqrstuvwxyz + apple
bcdfghijkmnoqrstuvwxyzaple

Задача

Напишите функцию, которая по ключевому слову или тексту делает алфавит для шифра Цезаря.

Возьмите свое имя как ключевое слово, получите алфавит. Зашифруйте этим алфавитом текст.

ENG_ALPHABET = "abcdefghijklmnopqrstuvwxyz"
def make_alphabet(keyword="apple", al=ENG_ALPHABET):
    '''
    abcdefghijklmnopqrstuvwxyz + apple
    bcdfghijkmnoqrstuvwxyzaple
    '''
    # тут нужно написать код
    pass

al2 = make_alphabet("tatyana")
text = "hello, world!"
coded_text = mycode(al2, ENG_ALPHABET)
print(text)
print(coded_text)

Шифр Вижнера

Статья в wikipedia

Добавляем ключевое слово (key word) для шифрования. Например, 'lemon'. Тогда для шифровки каждой буквы текста 'hello' используется свой сдвиг для построение алфавита цезаря.

Если текст больше, то слово 'lemon' повторяется столько раз, сколько нужно:

Исходный текст:       ATTACKATDAWN
Ключ:                 LEMONLEMONLE
Зашифрованный текст:  LXFOPVEFRNHR

Для шифрования руками делают 1 раз квадрат Виженера (tabula recta):

 0 a abcde fghij klmno pqrst uvwxyz
 1 b bcdef ghijk lmnop qrstu vwxyza
 2 c cdefg hijkl mnopq rstuv wxyzab
 3 d defgh ijklm nopqr stuvw xyzabc
 4 e efghi jklmn opqrs tuvwx yzabcd
 5 f fghij klmno pqrst uvwxy zabcde
 6 g ghijk lmnop qrstu vwxyz abcdef
 7 h hijkl mnopq rstuv wxyza bcdefg
 8 i ijklm nopqr stuvw xyzab cdefgh
 9 j jklmn opqrs tuvwx yzabc defghi
10 k klmno pqrst uvwxy zabcd efghij
11 l lmnop qrstu vwxyz abcde fghijk
12 m mnopq rstuv wxyza bcdef ghijkl
13 n nopqr stuvw xyzab cdefg hijklm
14 o opqrs tuvwx yzabc defgh ijklmn
15 p pqrst uvwxy zabcd efghi jklmno
16 q qrstu vwxyz abcde fghij klmnop
17 r rstuv wxyza bcdef ghijk lmnopq
18 s stuvw xyzab cdefg hijkl mnopqr
19 t tuvwx yzabc defgh ijklm nopqrs
20 u uvwxy zabcd efghi jklmn opqrst
21 v vwxyz abcde fghij klmno pqrstu
22 w wxyza bcdef ghijk lmnop qrstuv
23 x xyzab cdefg hijkl mnopq rstuvw
24 y yzabc defgh ijklm nopqr stuvwx
25 z zabcd efghi jklmn opqrs tuvwxy

Кто расшифровывает, тоже знает ключевое слово.

Этот шифр легко расшифровывается подбором длины ключевого слова. Защита лучше, если используется не ключевое слово, а ключевой текст, который равен длине шифруемого текста (не повторяется, а все время новый). Новая шифровка - новый ключевой текст. Для этого (дипломатическая переписка) у отправителя и у получателя были одинаковые шифровальные блокноты, которые содержали только ключевой текст. После использования текста страница блокнота вырывалась и уничтожалась.

Задача

Написать функции, которые по ключевому слову зашифровываю текст и расшифровывают текст.

def mycode(keyword, text):
    # тут нужно написать код
    t = text
    return t

def mydecode(keyword, coded_text):
    # тут нужно написать код
    t = coded_text
    return t

text = 'attack at dawn'

t1 = mycode('lemon', text)
print(t1)
t2 = mydecode('lemon', t1)
print(t2)

Шифрование по тексту

Возьмем текст, например, стихотворение как ключевой текст. Нужно зашифровать сообщение (текст). Вместо буквы, например, 'o' будем брать ее (первый) номер в строке 'hello, world'. Если буквы в строке нет, например, мы искали букву 'a', то будем писать -1.

Пример: шифруем текст 'tower'. Ключевой текст состоит из 1 строки-панаграммы ("The quick brown fox jumps over the lazy dog."

0        1         2         3         4      
012345678901234567890123456789012345678901234567890
The quick brown fox jumps over the lazy dog.
t -> 0
o -> 12
w -> 13
e -> 2
r -> 11

Получаем последовательность чисел:

0 12 13 2 11

Плохо, что одна и та же буква кодируется одним и тем же числом, такой шифр можно взломать частотным методом.

Будем искать не сколько букв от начала строки, а сколько букв от предыдущей найденной буквы. Начинаем с 0.

0        1         2         3         4      
012345678901234567890123456789012345678901234567890
The quick brown fox jumps over the lazy dog.
t -> 0    # от 0 до 0
o -> 12   # от 0 до 12
w -> 1    # от 12 до 13
e -> 15   # от 13 до 28
r -> 1    # от 28 до 29
q -> 17   # от 29 до конца 42 и от 0 до 4

Можно представить, что строка бесконечно повторяет себя и мы идем дальше по этой бесконечной строке.

0        1         2         3         4          5         6         7         8  
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
The quick brown fox jumps over the lazy dog.The quick brown fox jumps over the lazy dog

Если ключевой текст разбит на строки, то у нас или номер символа в строке, или -1, если символа нет. Закодируем так слово 'tower' текстом

  0123456789012
0 The quick 
1 brown fox 
2 jumps over 
3 the lazy dog.
Начинаем со строки 0
t -> 0
следующая строка 1
o -> 2
следующая строка 2
w -> -1 (буквы нет)
следующая строка 3
w -> -1 (буквы нет)
следующая строка 0
w -> -1 (буквы нет)
следующая строка 1
w -> 3
следующая строка 2
e -> 8
следующая строка 3
r -> -1 (буквы нет)
следующая строка 0
r -> -1 (буквы нет)
следующая строка 1
r -> 1

0 2 -1 -1 -1 3 8 -1 -1 1

Если вместо -1 -1 -1 писать -3, то получим зашифрованный текст:

0 2 -3 3 8 -2 1

Задача 1 - шифровка одной строкой

Взять 1 строку "The quick brown fox jumps over the lazy dog." и ей зашифровать ваше имя.

Задача 2 - шифровка многими строками

Взять стихотворение и зашифровать им ваше имя.

JABBERWOCKY by Lewis Carroll

Twas brillig, and the slithy toves
Did gyre and gimble in the wabe:
All mimsy were the borogoves,
And the mome raths outgrabe

Beware the Jabberwock, my son!
The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
The frumious Bandersnatch!

He took his vorpal sword in hand:
Long time the manxome foe he sought -
So rested he by the Tumtum tree
And stood awhile in thought.

And, as in uffish thought he stood,
The Jabberwock, with eyes of flame,
Came wiffling through the tulgey wood,
And burbled as it came!

One, two! One, two! And through, and through
The vorpal blade went snicker-snack!
He left it dead, and with its head
He went galumphing back.

And hast thou slain the Jabberwock?
Come to my arms, my beamish boy!
A frabjous day! Callooh! Callay!
He chortled in his joy.

Twas brillig, and the slithy toves
Did gyre and gimble in the wabe:
All mimsy were the borogoves,
And the mome raths outgrabe.


БАРМАГЛОТ (пер. Д. Орловской)

Варкалось. Хливкие шорьки
Пырялись по наве,
И хрюкотали зелюки,
Как мюмзики в мове.

О бойся Бармаглота, сын!
Он так свирлеп и дик,
А в глуще рымит исполин -
Злопастный Брандашмыг.

Hо взял он меч, и взял он щит,
Высоких полон дум.
В глущобу путь его лежит
Под дерево Тумтум.

Он стал под дерево и ждет,
И вдруг граахнул гром -
Летит ужасный Бармаглот
И пылкает огнем!

Раз-два, раз-два! Горит трава,
Взы-взы - стрижает меч,
Ува! Ува! И голова
Барабардает с плеч.

О светозарный мальчик мой!
Ты победил в бою!
О храброславленный герой,
Хвалу тебе пою!

Варкалось. Хливкие шорьки
Пырялись по наве,
И хрюкотали зелюки,
Как мюмзики в мове.

Набор задач

Задача 3.1: Числа в буквы

Замените числа, написанные через пробел, на буквы. Не числа не изменять.

Input Output
8 5 12 12 15 hello
8 5 12 12 15 , 0 23 15 18 12 4 ! hello, world!

Задача 3.2: буквы в числа

Дан текст. Замените каждую букву на число - порядковый номер буквы в алфавите. А на 1, В на 2, С на 3 и так далее.

Пробел заменять на 0. Другие символы оставлять как есть.

Числа печатайте через пробел.

Input Output
hello 8 5 12 12 15
Hello, world! 8 5 12 12 15 , 0 23 15 18 12 4 !

Задача 3.3: Убрать гласные буквы

В английском алфавите буквы eyuioa - гласные. Удалите из текста все гласные буквы.

Input Output
apple ppl
Good morning! Gd mrnng!

Задача 3.4: Оставить только НЕ гласные буквы

В английском алфавите буквы eyuioa - гласные. Удалите из текста все гласные буквы. Удалите из текста все НЕ буквы.

Input Output
apple ppl
Good morning! Gdmrnng

Задача 3.5: Убрать повторяющиеся буквы и лишние символы

Построим по ключевой фразе часть алфавита. Возьмем все буквы по одному разу. Не буквы убрать.

Буквы должны идти в том порядке, в котором встретились в первый раз.

Input Output
apple aple
Good morning! godmrni

Задача 3.6: Убрать из первого слова все буквы, которые есть во втором слове

Дан алфавит (все буквы уникальные) и сжатое ключевое слово (каждая буква встречается только 1 раз).

Построить новый алфавит, который состоит из сжатого ключевого слова и оставшихся букв алфавита.

Input Output
apple
abcdefghijklmnopqrstuvwxyz
aplebcdfghijkmnoqrstuvwxyz
godmrni
abcdefghijklmnopqrstuvwxyz
godmrniabcefhjklpqstuvwxyz

Задача 3.7: Убрать повторяющиеся буквы и лишние символы

Зашифруйте текст. Ключевой фразой возьмите свое имя. Сдвиг 3.

Устойчивость шрифтов с подстановками

Шрифты с подстановками легко взломать, зная как часто встречаются буквы в тексте.

220px-English-slf.png

Видно, что всего в английском языке встречается буква e.

Бинарный шифр

Поставим каждому символу свое число (по порядку)

Число в десятичной системе представляется как 495 = 4*102 + 9*101 + 5*102

Числа можно записывать как суммы степеней числа 2, а не 10. Это бинарное число.

10112 = 1*23 + 0*22 + 1*21 + 1*20 = 1*8 + 0*4 + 1*2 + 1*1 = 8+4+1 = 1310

пробел - 0 - 00000
a -  1 - 00001
b -  2 - 00010
c -  3 - 00011
d -  4 - 00100
e -  5 - 00101
f -  6 - 00110
g -  7 - 00111
h -  8 - 01000
i -  9 - 01001
j - 10 - 01010
k - 11 - 01011
l - 12 - 01100
m - 13 - 01101
n - 14 - 01110
o - 15 - 01111
p - 16 - 10000
q - 17 - 10001
r - 18 - 10010
s - 19 - 10011
t - 20 - 10100
u - 21 - 10101
v - 22 - 10110
w - 23 - 10111
x - 24 - 11000
y - 25 - 11001
z - 26 - 11010

Хотим зашифровать слово hello. Это числа

h -  8 - 01000
e -  5 - 00101
l - 12 - 01100
l - 12 - 01100
o - 15 - 01111

Выпишем бинарные числа.

01000 00101 01100 01100 01111

0 - маленькая буква, 1 - большая буква.

Зашифруем эту последовательность из 0 и 1 в тексте

Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex.

01000 00101 01100 01100 01111
010000010 10 110001 1000 1111
beautiful is better than ugly. explicit is better than implicit.
bEautifUl Is BEtteR? Than UGLY

Задача 4.0: Буквы в числа

Из строки получите список чисел.

Каждую букву замените на ее порядковый номер. А на 1, В на 2, С на 3 и так далее.

Пробел заменить на 0. Прочие символы удалить.

Input Output
hello [8, 5, 12, 12, 15]
Hello, world! [8, 5, 12, 12, 15, 0, 23, 15, 18, 12, 4]

Задача 4.1: Цифры числа

Напечатайте 4 последних цифры числа в обратном порядке.

Input Output
1279 [9, 7, 2, 1]
9876543206 [6, 0, 2, 3]
15 [5, 1, 0, 0]

Задача 4.2: Цифры числа в прямом порядке

Напечатайте 4 последних цифры числа в обратном порядке.

Input Output
1279 [1, 2, 7, 9]
9876543206 [3, 2, 0, 6]
15 [0, 0, 1, 5]

Задача 4.3: Бинарное представление числа

Дано число. Напечатайте его 6 последних бинарных цифр.

Input Output
5 [0, 0, 1, 0, 1]
1 [0, 0, 0, 0, 1]
[0, 0, 0, 0, 0]
15 [0, 1, 1, 1, 1]

Задача 4.4: НеРоВнЫй? ПоЧеРк?

В тексте напишите буквы в порядке "большая буква", "маленькая буква". Не буквы оставлять как есть. Они на порядок букв не влияют.

Input Output
hello HeLlO?
a.b,c A.b,C
Hello, Harry Potter! HeLlO?, HaRrY? pOtTeR!

Задача 4.5: НеРоВнЫй? ПоЧеРк? по образцу

Дан список из 0 и 1 - образец.

Дана строка. В строке букв больше, чем чисел в образце.

Буквы в строке должны стать большими и маленькими в таком порядке, который указан в образце. Если в списке очередное число 0, то буква маленькая. Если в списке очередное число 1, то буква большая.

Когда образец (список чисел) закончится,

case = [0, 1, 1, 0, 1, 0, 0, 1]
text = 'Hello, world!'

def encode(text, case):
    # тут нужно написать код

result = encode(text, case)
print(result)   # hELlO, woR
 

Задача 4.6: Бинарный шифр.

Напишите программу, которая шифрует ваше имя в этом тексте:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let's do more of those!

Attachment sort Action Size Date Who Comment
ceaserCipher.png manage 13.6 K 05 Feb 2019 - 10:17 TatyanaDerbysheva шифр Цезаря
220px-English-slf.png manage 3.2 K 05 Feb 2019 - 10:39 TatyanaDerbysheva