Загрузил aimgrund

Python для начинающих: Лучшие задачи для изучения языка программирования

для начинающих
Мировой
компьютерный
бестсемер
15 enigmes ludiques pour
s·initier а la programmation
Pascal LAFOURCADE
et
Malika MORE
Паскаль
Лафуркад
Малика
Мор
для начинающих
Лучшие задачи
для изучения языка
программирования
Мо сква
Originally puЫished in France as: 15 enigmes ludiques pour s'initier а la programmation
Python Ву Pascal LAFOURCADE and Malika MORE © Dunod 2022, Malakoff
Во внутреннем оформлении использова ны фотографии и ил люстрации:
Foto-Ruhrgeblet, Ricardo Javier, Renata Sedmakova, Woodpond, Prokradyha,
Studio Mazeve, ZKH , Bablch Alexander / Shutterstock / FOTODOM
Используется по лицензии от Shutterstock / FOTODOM;
© Bostoп Globe, NurPhoto / Gettyl mages.ru;
© Universal l mages Group / Universal History Archive / DIOMEDIA;
© Photos 12 Cinema / DR / DIOM EDIA;
© YМichael Debets/Pacific Press / Alamy / Legion-media;
© Dieter Е. Норре / akg-images / Alamy / Legion-media;
© SVEN SIMON / Alamy / Legion-media
Лафуркад, Паскаль.
Л29
Python для начинающих. Лучшие задачи для изучения языка программирова­
ния/ Паскаль Лафуркад, Малика Мор; [перевод с французского А. Золотова].
Москва: Эксмо, 2025. -
192 с. -
(Мировой компьютерный бестселлер).
Это практическое руководство для тех , кто хочет освоить программирование на языке Python. Состоит и з
15 увлекательных задач , которые помогут н овичкам освоить ключевые концепции программирования , решая
интерес ные кейсы и головолом ки. Изда ние ориентировано на читателей с любым уровнем подготовки.
Книга << Python для начинающих. Лучшие задачи для и зучения я з ыка программ ирования » станет ис­
точником вдохновения для начин аю щих программистов , за инте ресова нны х не только в овладении техниче-
скими навыка ми , но и в пои с ке оригинальных решений.
УДК ОО4.43
ББК 32.973.26-018.2
Все права защищены. Книга или любая ее часть не может быть скопирована, воспроизведена в электронной или
механической форме, в виде фотокопии, записи в память ЭВМ, репродукции или каким-либо иным способом, а
также использована в любой информационной системе без получения разрешения от издателя .
Копирование,
воспроизведение и иное использование книги или ее части без согласия издателя является незаконным и влечет
уголовную, административную и гражданскую ответственность.
Производственно-практи ческое издание
МИ РОВОЙ КОМ П ЬЮТЕРНЫ Й БЕСТСЕЛЛЕР
Лафуркад Паскаль , Мор Малика
PYTHON ДЛЯ НАЧИНАЮЩИХ
ЛУЧШИЕ ЗАДАЧИ ДЛЯ ИЗУЧЕНИЯ ЯЗЫКА ПРОГРАММИРОВАНИЯ
Главный редактор Р. Фасхутдинов
Руководитель направления В. Обручев
Ответственный редактор Л. Салихова
П родюсер В. Палитко
Н аучный редактор Н. Белявская
Литературный редактор М. Молчанов
Младш ий редактор П. Смирнов
Художественн ый редактор Е. Анисина
Компьютерная верстка Е. Матусовская
Корректоры А. Ярлыкова, Ю. Киреева
Страна происхождения: Российская Федерация
Ш ыrарушы ел: Ресей Федерациясы
ООО •Издательство «Эксмо"
123308, Россия, r. Москва, ул. Зорге, д. 1, стр . 1, эт. 20, каб. 2013 . Тел. 8 (4 95)411-68-86.
Home page: www.eksmo.ru E-mail: info@eksmo.ru
0ндiрушi: •Издательство •ЭКСМО• жшк,
123308, Ресей, М&екеу "3-"ЗСы, Зорге кешесi, 1-уй, 1 - ~рылыс, 20 кабат, 2013-каб.
Тел. : 8 (495) 411 -68-86. Home page: WININ.eksmo.ru E-mail: info@eksmo.ru.
Тауар белгiсi: «Эксмо»
Интернет-магазин : www.Ьook24.ru
Интернет-маrазин : www.Ьook24.kz
Интернет-дукен : www.Ьook24.kz
Импортёр в Республику Казахстан ТОО •РДЦ-Алматы" .
1<,азак;стан Республикасына импорттаушы •РДЦ-Алматы" ЖШС.
Дистрибьютор и представитель по приему претензий на продукцию
■11\ЧИТАЙ • ГОРОД
в Ресnубли11:е Казахстан: ТОО «РДЦ-Алматы »
Дистрибьютор жене 1<,аэак,стан Республикасында енiмге шаFЫмдар
к,абылдау ж:енiндегi екiл : «РДЦ-Алматы» ЖШС.
Алматы к,., Домбровский кеш. , З «а», литер Б, офис 1.
Тел. : 8(727) 251 -59-90/91/92. E-mail: RDC-AJmaty@eksmo.kz
БОМ БОРА - лидер на рынке полезных и вдохновляющих книг.
Мы любим книги и создаем их, чтобы вы могли творить , открывать
мир , пробовать новое, расти. Быть счастливыми. Быть на волне.
0 bombora.ru
КН И ЖНЫЙ МАГАЗИН
.
г.,
.
о техническом регулировании можно получить на сайте Издательства «Эксмо»:
Техникалык, реттеу туралы РФ за~амасына сай басылымны" сайкестiгiн растау
тураnы малiметтердi мына адрес бойынша алуFЗ болады : http://eksmo.ru/ certification/
О CD bombora
ТЕIРИТОРИs:1
•~
~
О bomborabooks
Сведения о подтверждении соответствия издания соmасно законодательству РФ
www.eksmo.ru/ certification
Произведено в Российской Федерации
Ресей Федерациясында ендiрiлrен
eksmo.ru
Официальный
Официальная франwиэа
интернет-м агазин
издательства « Эксмо•
издательства «Э кс мо»
СертификаттауFЗ жатпайды
Дата изготовления / П одписано в печать 01.10.2024.
Формат 70х100 1 / 16 . Печать офсетная . Усл. печ. л. 15,56.
Тираж
э кз. З аказ
ISBN 978-5-04-192646-5
Хоче ш ь стать
111 1 1111 1
9 785041 926465 >
ISBN 978-5-04-192646-5
автором «Эксмо»?
© Антон Золотов, перевод на русский язык, 2025
© Оформление. ООО «Издательство «Эксмо » , 2025
Содержание
Предисловие
..................................................... 9
1. PYTHON 3 ... ... .. .... .. ... .. ...... . ... .. ... .. ... .... . . .. . .... .... 11
Краткое введение
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2. головоломки ... ..... ............... .................. .. ....... 19
1. Аскет*
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2. Криптарифм * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3. Кулинарная лопатка *
4. Шадоки считали *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5. Стеганография* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
6. Скрытые каналы *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
7. Раскраска в два цвета * * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
8. Электронное голосование * * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
9. Биткоин * *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
10. Сиракузы**
................ . ................. ..... ........ 45
11. Кривые Безье** ............................................ 47
12. Во времена древних греков**
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
13. Четверичное дерево** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
14. Семь мостов Кёнигсберга * * *
15. Точный счет * * *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3. ПОДСКАЗКИ ... НА ВСЯКИЙ СЛУЧАЙ ........ .. ........... .... . . 61
1. Подсказки первого уровня . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
2. Подсказки второго уровня . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3. Подсказки третьего уровня . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
0
Содержание
4. РЕШЕНИЯ .......... . ....................................... . ... . . 73
1. Аскет*
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
2. Криптарифм * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3. Кулинарная лопатка *
4. Шадоки считали *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
5. Стеганография* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
6. Скрытые каналы *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
7. Раскраска в два цвета** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
8. Электронное голосование** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
9. Биткоин * * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
1О. Сиракузы * *
137
11. Кривые Безье** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
12. Во времена древних греков**
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
13. Четверичное дерево** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
14. Семь мостов Кёнигсберга * * * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
15. Точный счет * * *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Список иллюстраций
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
Список аббревиатур
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
Алфавитный указ атель
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Всем, кто готов программировать и зарабатывать этим деньги
Предисловие
Пятнадцать головоломок, собранных в этой книге, позволят вам приоб­
рести необходимые навыки программирования и вместе с тем неплохо про­
вести время. Их решение требует логики, размышлений, а иногда -
хитрости,
однако для понимания вполне достаточно знаний на уровне средней школы.
В середине книги есть специальный раздел, где для каждой головоломки
предложены подсказки трех последовательных уровней. Если вы вдруг забук­
совали и не знаете, что делать дальше, эти подсказки помогут вам найти путь
к решению.
Уровень сложности головоломки обозначен звездочками. Есть голово­
ломки легкого уровня
*. Их под силу решить каждому, достаточно лишь не­
которой усидчивости. Требуемый код, как правило, довольно простой.
Решение головоломок промежуточного уровня
* * потребует более
сложных размышлений или вычислений. Иногда нужно будет применять
приемы не столь очевидные, как на первом уровне. Для написания программ,
несомненно, понадобится приложить больше усилий.
И наконец, есть две сложные головоломки
* * *, решение которых по ­
требует большего напряжения, а также продвинутых математических и ком­
пьютерных навыков. Для составления необходимых программ придется про ­
явить определенное упорство.
Эта книга предназначена в первую очередь для учащихся средних спе­
циальных учебных заведений соответствующего профиля. Цель книги представить задачи, которые можно решить с помощью программ на языке
Python 3, хотя на самом деле программы можно писать и на любом другом
языке программирования, который вам хорошо знаком. В начале книги мы
посвящаем несколько страниц описанию основных команд Python 3, которые
пригодятся для решения головоломок.
Темы головоломок дают во зможность познакомиться со многими важны­
ми понятиями информатики. Основную часть книги составляют детальные
0
Предисловие
решения всех головоломок. Каждое решение содержит не только программу
на языке Python 3, с помощью которой решается головоломка, но и подробное
объяснение того, как алгоритм был составлен. Каждое решение сопровожда­
ется научной или литературной цитатой, связанной с темой головоломки или
ее решением.
Игровая составляющая данной книги послужит дополнительным стиму­
лом для многих читателей и подтолкнет их к творческому подходу при со­
ставлении программ для решения головоломок .
Эта книга ориентирована на тех, кто любит программировать. В ней
представлены задачи, доступные для программистов и помогающие узнать
важные элементы информатики . Косвенно она также адресована всем препо­
давателям информатики, которые хотят обучить своих учеников программи­
рованию на Python 3. Настоящий сборник головоломок представляет собой
банк упражнений, пригодных для включения в учебную программу.
Головоломки, подсказки и решения содержат многочисленные врезки:
биографические, исторические, культурные, технические, математические,
связанные с языком Python 3, решения на языке Python 3, -
а также полезные
советы для педагогов. Каждая врезка обозначена соответствующим значком:
Благодарности: Мы благодарим Седрика Лораду за то, что подсказал нам
путь к созданию этих головоломок. Мы также выражаем нашу благодарность
Флавьену Бине, Генаэль де Жюли, Эммануэлю Диле, Кристин Сольнон и Тибо
Рали за их вклад в подготовку этой книги. Кроме того, мы адресуем нашу сер­
дечную признательность Жан-Люку Блану, Матье Даниэлю и Анн Ле Дюк за
их замечания и конструктивные предложения, сделанные после тщательного
прочтения этой книги.
Малика Мор и Паскаль Лафуркад
Клермон -Ферран, 13 сентября 2022 год
0
1
Краткое введение
Все решения головоломок для наглядности приводятся на языке Python 3,
бесплатном и свободном для скачивания*. Разумеется, решения можно пи­
сать на любом другом языке программирования по вашему выбору, имею­
щем функции для арифметических вычислений, присваивания переменных,
выполнения условных операторов и циклов (while ), что необходимо для на­
писания требуемых алгоритмов.
В данной главе описаны команды, наиболее часто используемые при ре­
шении представленных головоломок. Иногда в тексте книги или подсказках
приводятся дополнительные сведения. Для получения более подробной ин ­
формации о Python 3, а также для систематизированного изучения програм­
мирования на этом языке существует множество пособий** и специализиро­
ванных сайтов с курсами. Рекомендуем начать с официального руководства,
доступного в интернете по адресу https://docs.python.org/3/, хоть оно и не
самое простое. Если вы уже хорошо знакомы с Python 3, то, скорее всего,
вам не придется обращаться к этой главе; в противном случае будет нелиш­
ним заглянуть сюда за помощью, если для программирования правильного
решения какой-либо из головоломок вам не хватает уже известных инст­
рументов.
Прежде всего отметим, что в Python 3 символ«#» используется для ком­
ментирования остальной части строки, а значит, все написаное после этого
символа в той же строке не будет учтено при выполнении программы. Другое
необходимое знание- важную роль в Python 3 играют табуляции (отступы),
и их наличие или отсутствие в нужных местах может изменить поведение
программы и даже привести к возникновению ошибок. И третье -
чтобы
разбивать длинный текст, в Python 3 существует оператор «\», известный
* https://www.python.org.
** Например: Julien Guillod, Programmation Python par la pratique ProЫemes et exercices
corriges, Dunod, 2021.
G
Краткое введение
также как принудительный перенос строки. Он разбивает одну длинную не­
прерывную строку на несколько коротких, более удобных для чтения.
1
2
string = «Этот» + « текст» + « просто» + « чересчур» + « длинный,»\
+ « чтобы» + « отображать» + « его»+ « на» + « одной» + « строке.»
Присвоение и простые математические операции
Символ «=» используется для того, чтобы присвоить значение выражения
переменной. Например, две команды х
= 3 и х = х + 1 последовательно при­
сваивают переменной х значение 3, а затем значение 3 + 1, т. е. 4.
Числовые операции сложения, вычитания, умножения, деления и возве­
дения в степень, а также логические (булевы) операции отрицания, и,
или
обозначаются соответственно а+Ь , а-Ь , а*Ь , а/Ь , а**Ь ,
not а , а and Ь , а or
Ь. Для деления с остатком, если а = Ь . q + r при О ~ r < Ь, то q = а/ /Ь, а r = а %Ь
или r = di vmod (а , Ь) .
В случае, когда эти операции возможны, для преобразования переменной
у в целое число пишут х = int (у) , а для преобразования переменной х в стро­
ку символов пишут у = str (х) .
Условный оператор if
Для выражения условия используются ключевые слова if, else и elif.
В приведенном ниже коде переменной res присваивают значение 3, если зна­
чение переменной х строго больше 3; иначе, если х равно нулю, то res прини­
мает значение О ; в противном случае res принимает значение 1.
1
2
3
4
5
6
if х > 3:
res = 3
elif х == О :
res = о
else:
res = 1
Обратите внимание, что запись «==», используемая при проверке условий,
отличается от символа присваивания. Кроме того, обязательными являются
как символ «: » после сравнения, так и табуляция в строках после условных
операторов . Части программы, соответствующие elif и else, используются
1. Python 3
только в том случае, когда это необходимо по алгоритму; в противном случае
они могут быть опущены.
Обычными операторами сравнения являются: а < Ь , а <= Ь, а > Ь , а >= Ь ,
а == Ь и а
!= Ь (для а, отличного от Ь ).
Циклы while и for
Следующая программа выводит на экран целые числа от О до 9 с помо­
щью цикла while:
i=O
1
2
while (i<l O) :
print (i)
3
4
#0 1 2 3 4 5 б 7 8 9
i=i+l
Следующая программа делает то же самое с помощью цикла f or. В Python 3
функция range (i) возвращает набор целых значений от О до i - 1:
f or i in range (1О ) :
print (i)
#0 1 2 3 4 5 б 7 8 9
1
2
Строки символов
•
Пустая символьная строка обозначается ««»» (пара кавычек без про­
бела между ними).
•
Для объединения двух строк, например, "фото" и "выставка", доста­
точно использовать символ сложения« +» . Таким образом, объедине­
ние строк « фото» и «выставка» будет равно «фотовыставка».
•
Функция chr позволяет преобразовать целое число в символ, для ко­
торого оно является кодом ASCII*, если такой символ существует. На­
пример, код chr (97) возвращает букву ' а ', а chr (122) возвращает букву
' z ', однако chr (123456789) вызовет ошибку, поскольку в таблице кодов
ASCII столь больших значений просто нет.
•
В общем случае разницы между одинарными « ' » и двойными « "» кавыч­
ками для обозначения символьной строки (см. примеры выше) нет.
* American Standard Code for Information Interchange.
G
Краткое введение
Считывание данных из файла
Чтобы не перепечатывать текст вручную, данные, необходимые для ре­
шения тех или иных головоломок, содержатся в файлах, которые можно ска­
чать по адресу https://addons.eksmo.ru/it/Enigmes.zip.
Поэтому важно знать, как считывать эти данные, чтобы работать с ними
в Python 3.
Следующая программа считывает слова из файла f. txt построчно, одно
за другим:
file = open(' f.txt' , ' r')
for line in file :
for word in line .split() :
print (word)
f ile. close ()
1
2
3
4
5
Следующая программа позволяет считывать содержимое файла f . txt по ­
символьно:
file = open(' f.txt' , ' r ')
character = fil e. read(l)
while character :
print (character)
character = file . read(l)
f ile. close ()
1
2
3
4
5
6
Списки
Пустой список обозначается пустыми квадратными скобками: « [] ». Для
добавления элемента х в конец списка L используется оператор L.append (х).
Для доступа к первому элементу списка L следует написать L [О] , поскольку
в Python 3 индексы списков начинаются с О . Чтобы получить последний эле­
мент списка, можно написать L [ - 1] .
1
1
L=[]
2 L.append (4)
3 _L.append (S)
1. Python 3
4
5
6
7
8
9
L. append (6)
print (L)
print (L [1])
print (len (L) )
print (L[ -1 ])
print (L[ len (L) - 1])
# [4 , 5, б]
#5
# Выводит 3, количество элементов в списке L
# Выводит последний элемент списка L
# Выводит последний элемент списка L
Функции и передача параметров
Чтобы определить функцию в Python 3, мы должны использовать клю­
чевое слово def, за которым следует имя функции, например, exchange, как
в приведенном ниже примере, затем задать в скобках параметры функции в нашем случае х и у .
1
def exchange(x, y) :
2
3
х=х+у
у= х-у
4
5
6
7
8
9
х = х-у
return ( х , у )
а=З
Ь=4
print (exchange (З , b ) )
10 print (a, b)
# Выводит (4, 3)
# Выводит 3 4
Переменные, определенные внутри функции, называются локальными
и не имеют никакой связи с переменными, определенными вне функции, хотя
могут иметь такие же имена.
Локальные переменные существуют только внутри функции и получают
значения при ее запуске. В примере выше х принимает значение 3, а у - зна­
чение переменной Ь, т. е. 4.
В Python 3 так называемые неизменяемые объекты, то есть целые числа
и символьные строки, могут быть переданы в функции как значения. Это
означает, что их значение не может быть изменено функцией.
С другой стороны, изменяемые объекты, такие как списки, передаются
в функции как ссылки (см. пример ниже) . Это означает, что их значение мо­
жет быть изменено функцией:
G
Краткое введение
1
def addLi st(my_li st , х) :
2
my_l is t. append(x)
3
4
L= [l , 2, 3]
5
6
7
print( L)
# [1 , 2, 3]
addLi st(L, 4)
print( L)
# [1 , 2, 3, 4]
Изменения в списке, переданном в качестве параметра фукнции, действу­
ют на список, определенный вне функции addList.
Библиотеки
В Python 3 есть возможность подключения библиотек, в основном темати­
ческих, состоящих из уже запрограммированных функций. Для этого в нача­
ле программы необходимо указать имя библиотеки, предварив его ключевым
словом import. Например, import math позволяет использовать при написании
программы математические функции mat h. е хр (х ) ,
или
ma th . sqrt (х) , ma th . cos (х )
math . si n ( х ), которые, соответственно, вычисляют экспоненту, квадрат­
ный корень, косинус и синус числа х.
В Python 3 доступны и другие библиотеки, такие как, например, библи­
отеки random или time. Библиотека random позволяет генерировать случайные
числа. С помощью команды t i me () из библиотеки t i me можно узнать текущее
время и измерить таким образом, например, продолжительность выполне­
ния программы.
1
2
3
4
5
import time
import random
start = time.time()
r = random.randint(l0,100)
end = time ()
duration = end - start
# Отображает текущее время
# Случайным образом выбирает целое число в диапазоне от 10 до 100
Также можно добавить библиотеки, которые по умолчанию в Python 3 не
включены. Например, чтобы добавить библиотеку turtle, необходимую для
решения головоломки 11, можно использовать следующую команду:
pythonЗ
-m pip install turtle
G
Краткое введение
Для удобства в Python 3 библиотеки можно переименовывать. Например,
библиотека numpy в приведенной ниже программе обозначается сокращен­
но
np.
1
2
import nurnpy as np
3
4
5
6
zeros = np.zeros([l0,10])
ones = np.ones([l0,10])
t = np . linspace ( З , 4, 11)
print(t )
# Строит матрицу размером 1О х 1О , заполненную нулями
# Строит матрицу размером 10 х 10, заполненную единицами
# Строит список из 11 значений от 3 до 4
# [3 . 3.1 3.2 3.3 3.4 3.5 3.6 3. 7 3.8 3.9 4. )
Основные библиотеки, которые понадобятся вам для решения головоло­
мок, следующие: pil (головоломка 5), pycryptodome (головоломка 9), turtle (го­
ловоломка 11) и numpy (головоломка 13). Они по мере необходимости описаны
в соответствующих врезках.
f Гвидо ван Россум (1956 r. р.)
Язык
Python был создан Гвидо
ван Россумом в феврале 1991 года.
В то время он читал сборник скетчей
из британского телевизионного ко­
медийного сериала «Летающий цирк
Монти
Пайтона»
(Monty Python's
Flying Circus), транслировавшего ­
ся ВВС в 1970-х годах. Он искал ко­
роткое, уникальное и немного зага­
дочное
название
для
своего
языка
программирования и выбрал Python
в честь этого шоу, фанатом которо­
го был.
Рис. О. Гвидо ван Россум
Что касается следующих версий языка Python, важно знать, что вер­
сия 2 несовместима с версией 3, поскольку в нее было внесено множество
изменений синтаксиса. Кроме того, с 2020 года версия Python 2 больше не
обновляется.
0
2
1
Аскет*
1059 32 1082 1072 1078 1076 1086 1075 1086 32 1087 1086 1082 1086 1083
1077108510801103 32 10771089 1090 1100 32108910741086108132 10921080
1083 1086 1089 1086 1092 44 32 1087 1080 1089 1072 1090 1077 1083 1100 32 1080
1083 1080 32 1093 1091 1076 1086 1078 1085 1080 1082 44 32 1082 1086 1090 1086
1088 1099 1081 32 1079 1072 1093 1074 1072 1090 1099 1074 1072 1077 1090 32
1080 32 1074 1086 1087 1083 1086 1097 1072 1077 1090 32 1074 32 1089 1077 1073
1077 32 1080 1076 1077 1102 32 1074 1088 1077 1084 1077 1085 1080 46 32 1048
1085 1086 1075 1076 1072 32 1101 1090 1080 32 1092 1080 1083 1086 1089 1086
1092 1099 32 1087 1086 1083 1091 1095 1072 1102 1090 32 1087 1088 1080 1079
1085 1072 1085 1080 1077 32 1087 1088 1080 32 1078 1080 1079 1085 1080 44 32
1085 1086 32 1095 1072 1097 1077 32 1074 1089 1077 1075 1086 32 1080 1084 32
1087108810801093 108610761080 1090 10891103 32 1078 107610721090 1100
44 32 1087 1086 1082 1072 32 1085 1072 32 1085 1080 1093 32 1085 1072 1083 1086
1078 1080 1090 32 1089 1074 1086 1081 32 1086 1090 1087 1077 1095 1072 1090
1086 1082 32 1074 1088 1077 1084 1103 46 32 1053 1077 1079 1072 1074 1080 1089
1080 1084 1086 32 1086 1090 32 1090 1086 1075 1086 44 32 1073 1091 1076 1077
1090 32 1083 1080 32 1101 1090 1086 32 1087 1088 1080 1079 1085 1072 1085 1080
1077 32 1085 1077 1084 1077 1076 1083 1077 1085 1085 1099 1084 32 1080 1083
1080 32 1079 1072 1087 1086 1079 1076 1072 1083 1099 1084 44 32 1101 1087 1086
1093 1072 32 1086 1090 1084 1077 1095 1077 1085 1072 32 1101 1090 1080 1084
1080 32 1083 1102 1076 1100 1084 1080 44 32 1074 1099 1088 1072 1078 1072 1102
1097 1080 1084 1080 32 1089 1074 1086 1080 32 1080 1076 1077 1072 1083 1099
32 1074 32 1096 1077 1087 1086 1090 1077 32 1089 1090 1080 1093 1086 1074 32
1080 1083 1080 32 1074 32 1075 1088 1086 1093 1086 1090 1077 32 1087 1086 1083
1080 1090 1080 1095 1077 1089 1082 1086 1075 1086 32 1076 1074 1080 1078 1077
1085 1080 1103 46 32 1059 32 1085 1072 1096 1077 1075 1086 32 1087 1086 1082
1086 1083 1077 1085 1080 1103 32 1077 1089 1090 1100 32 1092 1080 1083 1086
1089 1086 1092 46 32 1054 1085 32 1085 1077 32 1093 1091 1076 1086 1078 1085
1080 1082 32 1080 32 1085 1077 32 1087 1080 1089 1072 1090 1077 1083 1100 46
32 1054 1085 32 1087 1088 1086 1075 1088 1072 1084 1084 1080 1089 1090 46 10
Рис. 1. Закодированный текст
0
2. Головоломки
Задача к головоломке 1
Разобравшись с используемым алгоритмом кодирования, сможете ли вы
написать на Python 3 программу для декодирования текста на рис. 1?
Решение на с. 75
G
2
Криптарифм
*
Буквы в приведенной ниже математической операции заменяют собой
различные цифры от О до 9. С помощью программы нужно определить зна­
чение каждой буквы так, чтобы операция давала верный результат при усло­
вии, что с нуля число начинаться не может (другими словами, S -:t- О и М -:t- О) .
SEND
+ MORE
MONEY*
Задача к говоломке 2
Можете ли вы написать на Python 3 программу для решения этого крип­
тарифма путем определения значения всех букв и расшифровать число, запи­
санное словом MONROE?
Решение на с. 83
Общие сведения
Существует много других криптарифмов, вот некоторые из них:
ВОЛК+ ЛИСА= ЗВЕРИ
кто+ кот = ток
КОШКА+ КОШКА+ КОШКА= СОБАКА
СИНУС+ СИНУС+ КОСИНУС = ТАНГЕНС
CHEVAL + VACHE = OISEAU
HUIT + HUIT = SEIZE
UN + UN + NEUF = ONZE
CINQ + CINQ + VINGT = TRENTE**
* Шлите больше денег (англ.).
** Перевод с фр. :
ЛОШАДЬ + КОРОВЫ
= ПТИЦА
ВОСЕМЬ + ВОСЕМЬ = ШЕСТНАДЦАТЬ
ОДИН + ОДИН + ДЕВЯТЬ
= ОДИННАДЦАТЬ
= ТРИДЦАТЬ
ПЯТЬ + ПЯТЬ + ДВАДЦАТЬ
0
2. Головоломки
Последние три примера относятся к категории, пользующейся особой
популярностью у знатоков: арифметические криптарифмы -
операции,
точные как для букв, так и для чисел*.
Правда, стоит заметить, что программа, составленная для решения
нашей конкретной головоломки, другие криптарифмы решать не сможет.
Очевидно, что алгоритм или программа, способные ответить только на
один вопрос, не очень интересны, поскольку не универсальны. Например,
вся польза изучаемого в школе алгоритма сложения заключается именно
в его абсолютной универсальности, так как позволяет складывать любые
числа, а не только 12 + 30
= 42. Однако общие алгоритмы или программы,
как правило, более сложны, чем алгоритмы или программы, созданные для
ответа только на один вопрос.
~
Например, чтобы помочь Пьеру (П) выйти из лабиринта, изображенно­
го на рисунке выше, можно придумать следующий алгоритм «на случай » :
пройти один шаг на север, затем один шаг на восток, затем два шага на юг,
два шага на запад и т. д. Впрочем, существует множество алгоритмов вы­
хода из любого лабиринта, например алгоритм Пледжа, хотя они гораздо
сложнее.
Сможете ли вы написать более общий алгоритм для решения разных
криптарифмов? Вот несколько подсказок:
а)
необходимо определить количество неизвестных, но выбор их име­
ни не важен;
6)
необходимо определить, какие неизвестные сгруппированы в числа
и коэффициент (1, 10, 100, 1000 и т. д.) каждого из них в составе этих
чисел;
в)
и что принципиально важно, необходимо определить арифметиче­
скую операцию между этими числами.
*
Для русского языка таких еще не придумали. -
0
Прим. пер.
3
Кулинарная лопатка
*
У кулинара-любителя блины получаются всегда разного размера. Когда
он их печет, то складывает в стопку, один за другим. Увидев, что блины сло­
жены как попало, он хочет упорядочить их по ра змеру, расположив самые
большие внизу, а самые маленькие щийся у него инструмент -
вверху стопки. Единственный имею­
кулинарная лопатка, которую можно подсунуть
под любой блин и перевернуть всю часть стопки, находящуюся сверху.
Задача к головоломке 3
Можете ли вы написать на Python 3 программу для упорядочения по раз­
меру любой стопки блинов при помощи одной только лопатки?
Решение на с. 93
Рис. 2. Картонные блины и кулинарная лопатка
0
2. Головоломки
яlв Зачем сортировать?
Классификация данных -
это деятельность, которой долгие годы за­
нимаются многочисленные государственные ведомства. Исторически сло­
жилось, что одной из первых задач, поддавшихся автоматизации, стала об­
работка данных переписи населения в США. В 1890 году Герман Холлерит
принял участие в конкурсе, организованном правительством США, и по­
строил первую статистическую машину. Эта машина автоматически сор­
тировала перфокарты. Впоследствии такие крупные компании, как IBM,
предложили несколько моделей, например модель DЗ, которая могла сор­
тировать 1000 карточек в минуту (рис. 3). В большинстве этих машин ис­
пользовался алгоритм поразрядной сортировки, который оказался очень
эффективен в конкретном случае с перфокартами.
Рис. 3. Сортировщик IBM D3, выпущенный на рынок в 1958 году
Организация, приведение в порядок и сортировка огромного количест­
ва данных
-
утомительные операции для человека, в то время как компью­
тер справляется с этими повторяющимися задачами гораздо качественнее.
Существует множество способов запрограммировать компьютер на сор ­
тировку данных. Ведущие специалисты по информатике исследовали этот
вопрос, стремясь разработать наиболее эффективные алгоритмы сорти­
ровки или доказать, что есть предел, дальше которого улучшить алгоритм
невозможно. В настоящее время, из-за резкого увеличения объема данных
в интернете, алгоритмы сортировки используются все чаще и чаще.
0
Шадоки считали
4
*
Для счета у шадоков существует собственная система счисления, осно­
ванная исключительно на следующих слогах: GA, BU, ZO и MEU. Вот пример
их числа:
BU MEU ZO MEU GA GA
Задача к головоломке 4
Можете ли вы написать программу, способную конвертировать числа
шадоков в десятичные (то есть в те, которыми пользуются люди), и узнать,
какое число скрывается за приведенным выше числом в записи шадоков?
Решение на с. 102
@\
u шадоки
«Шадоки» -
юмористический французский мульт­
;t,_ ~ ~ d,,,., ~ -
сериал, впервые показанный по телевидению в апре­
ле 1968 года. Поэтичный и забавный, он состоит из
четырех сезонов и двухсот восьми серий продолжи­
тельностью две-три минуты каждая. Его создатели сценарист Жак Руксель и художник-мультиплика­
тор Жан Поль Кутюрье. Незабываемый закадровый
голос принадлежит актеру Клоду Пьеплю. На рис. 4
изображен шадок, пытающийся наполнить стакан
жидкостью из бутылки Клейна. Подписью к иллюс­
трации
служит
известная
шадокская
пословица:
«Если нет решения, то нет и з адачи». Она восходит
к знаменитому высказыванию Альберта Эйнштей­
на: «Задача без решения -
это плохо поставленная
задача» . А в названии головоломки обыграно основ­
ное занятие шадоков: « Шадоки качали ... ».
0
s,'iL N'Y f\ Р'\ ~ J)E: ~ot.- uтiotJ
С е'SТ- l}U 'iL r,, У А РА~ .РЕ: f>R_O/>L..EME:.
Рис. 4. Шадок
2. Головоломки
С~ Бутылка Клейна и лента Мёбиуса
Бутылка Клейна -
это замкнутая односто­
ронняя поверхность без краев. Она не имеет ни
«внутренней», ни «внешней» стороны. Такую
поверхность придумал в
1882 году немецкий
математик Феликс Клейн.
собой
абстрактный
Она представляет
математический
объект,
который не может существовать в обычном
трехмерном пространстве (иначе говоря, это
непогружаемый
объект).
В
двухмерном
или
трехмерном изображении, например на рис. 5,
горлышко проходит через тело бутылки, тогда
Рис. 5. Бутылка Клейна
как в реальности (если так можно выразиться)
пересечение
происходит в
четвертом
измере­
нии, не образуя отверстия в теле.
Аналогичным объектом, однако «погружае­
мым», является лента Мёбиуса (рис. 6). Ее при­
думали в
1858 году независимо друг от друга
математики Август Фердинанд Мёбиус ( 17901868) и Иоганн Бенедикт Листинг (1808-1882).
Рис. 6. Лента Мёбиуса
Технически это компактная поверхность, ребро которой гомеоморфно
окружности. Такая поверхность имеет только одну сторону -
в отличие
от обычной ленты, у которой их две. С практической точки зрения ленту
Мёбиуса легко изготовить из полоски бумаги, если склеить ее концы, пред­
варительно один из них развернув. Математически лента Мёбиуса описы­
вается системой уравнений:
х = (2 + v соs(и)) соs(2и)
!
у= (2 + v cos(u)) sin(2u)
z = v sin и
Если представить, что лента Мёбиуса рас­
тягивается до тех пор, пока не сомкнется сама
с собой (что трудно вообразимо в трехмерном
пространстве), то получится бутылка Клейна.
Символ, обозначающий перерабатываемые ма­
териалы, используется с 1970 года и напомина­
ет ленту Мёбиуса.
Рис. 7. Символ
перерабатываемых
материалов
0
Стеганография
5
*
В РNG-файле, содержащем изображение с рис. 8 -
логотип Python 3
(в файле он цветной), скрыт секретный текст.
Рис. 8. Логотип Python
Задача к головоломке 5
Сможете ли вы определить, где спрятан секретный текст, и написать
программу для его распознания?
Решение на с. 109
/ nиксеnь
Цифровое изображение, как мозаика, состоит из маленьких квадрати­
ков, называемых пикселями. Например, изображение размером 640 х 480
имеет ширину 640 пикселей и высоту 480 пикселей. Каждому пикселю при­
своен цвет, представленный одним или несколькими числами. Слово «пик­
сель» -
это сокращение от PICture ELement, что в переводе с английского
означает элемент изображения. Изображения могут быть черно-белыми,
полутоновыми или цветными.
RGB
Система цветового кодирования RGB соответствует аддитивной моде­
ли синтеза цвета в оптике, то есть цвет определяется как сумма трех компо­
нентов: красного, зеленого и синего.
2. Головоломки
RGB
Отсюда и название системы, образованное от английских наименова­
ний этих цветов: Red, Green, Blue. Именно она используется в компьютер­
ных дисплеях.
Цвет пикселя определяется с помощью трех чисел в диапазоне от О
ДО 255 (или от 00000000 ДО 11111111 в ДВОИЧНОМ формате, или от О ДО FF
в шестнадцатеричном формате), каждое из которых соответствует 8 битам.
Первое число обозначает пропорцию красного, второе ного, а третье
-
пропорцию зеле­
синего.
Три одинаковых значения соответствуют более светлым или более тем­
ным оттенкам серого: от белого до черного. Иные комбинации образуют
другие смешанные цвета.
Цвет
R (красный)
G (зеленый)
В (синий)
Красный
255
о
о
Зеленый
о
255
о
Синий
о
о
255
Желтый
255
255
о
Голубой
о
255
255
255
о
255
Черный
о
о
о
Темно-серый
50
50
50
Светло-серый
200
200
200
Белый
255
255
255
Пурпурный
В общей сложности система RGB позволяет представить 2563
= 16 777 216
цветов, что значительно превышает полмиллиона или около того цветов, ко­
торые в лучшем случае способен различать человеческий глаз. Существуют
и другие системы кодирования цвета, например четырехкрасочная, которая
используется в печати с XVIII в. В начале ХХ в. она была стандартизирова­
на под названием СМУК*. Цвета получаются путем смешивания красок или
чернил: например, из голубого и желтого образуется зеленый. Такой подход
соответствует субтрактивной модели синтеза цвета в оптике.
*
СМУК, или СМУ+К, -
расшифровывается как Cyan, Magenta, Yellow, Кеу (или
ЫасК) , в переводе с англ. это голубой, пурпурный , желтый и ключевой (или черный).
0
5. Стеганография
J
*
PIL
Для работы с изображениями в Python 3 можно использоваться биб­
лиотеку PIL*. Приведенная ниже программа позволяет выводить числовые
значения цветов каждого пикселя в формате RGB для РNG-изображения,
сохраненного под именем
1
Myimage. png.
from PIL import Image
2
3
4
png = Image . open ("Myimage . png")
pixels = png .getdata()
5
6
7
for rgb in pixels:
print (rgb[O] , rgb [l ], rgb[2] , rgb[3])
Для тестирования этой программы лучше всего выбрать изображение
с небольшим количеством пикселей (не более нескольких сотен), иначе вре­
мя обработки будет очень долгим. Элемент rgb [ О] списка rgb содержит зна­
чение красной составляющей рассматриваемого пикселя, элемент rgb [1] значение зеленой составляющей пикселя, элемент rgb [2] -
значение синей
составляющей пикселя, и наконец, элемент rgb [3] содержит дополнитель­
ную информацию: значение уровня прозрачности пикселя (его «альфа-зна­
чение», обозначаемое греческой буквой а).
*
Команда для установки этой библиотеки: pip install pillow.
0
б
Скрытые каналы
*
Функция checkpi n в приведенной ниже программе позволяет проверить,
соответствует ли введенное польз ователем слово, содержащееся в перемен­
ной attempt, заданному секретному РIN-коду pin.
1
import time
2
3
global pin
4
5 def checkpin(test):
6
for i in range (len(pin)) :
7
time .sleep(l)
8
if pin[i] != test [i] :
9
return( False)
10
return (True )
11
12 pin=input ( " Bвeдитe РIN - код из 6 цифр для проверки : " )
~ Глобальные переменные
В Python 3 ключевое слово global используется для обозначения глобаль­
ной переменной. Особенность такой переменной в том, что она доступна
для чтения и записи из любого места программы, без необходимости пере­
давать ее в качестве параметра функции. Этим она отличается от локальных
переменных, определяемых только внутри функции.
Использовать глобальные переменные не рекомендуется начинающим, -
особенно
поскольку это затрудняет понимание программы. Также
сложно контролировать, какие части программы изменяют эти перемен­
ные и когда, что затрудняет поиск ошибок.
6. Скрытые каналы *
В данной же головоломке этот способ позволяет использовать пере­
менную pin в функции checkpin, не передавая ее в качестве параметра и тем
самым избегая сообщения «программа не может получить доступ к пере­
менной pin».
Задача к головоломке 6
Сможете ли вы написать на Python 3 программу, которая позволит ва­
шему компьютеру менее чем за три минуты распознать секретный РIN-код,
введенный пользователем?
Обратите внимание, что необходимо соблюдать следующее ограничение:
программа не должна получать доступ к переменной pin напрямую, а должна
использовать функцию checkpin.
Решение на с. 117
Ш РIN-код
Сокращение
PIN происходит от английского Personal Identification
Number (персональный идентификационный номер). Такие номера были
введены в 1967 году с появлением первых банкоматов, которые использо­
вались для выдачи банкнот в обмен на специальный ваучер (чек). В 1972 го­
ду Lloyds Bank представил первый банкомат с магнитными картами, в ко­
торых использовались PIN- коды. Это конфиденциальный код, состоящий,
как правило, минимум из 4 цифр. Он служит для аутентификации личности
владельца банковской карты, а также для разблокировки SIМ-карт телефо­
нов или смарт-карт. Первый РIN-код был изобретен Джеймсом Гудфеллоу.
Отличие этих кодов от паролей в том, что они состоят только из цифр
от О до 9, поэтому количество возможных комбинаций ограничено. Чтобы
избежать атак методом перебора, системы часто ограничивают количество
попыток, блокируя доступ после нескольких ошибок.
РIN-коды слабее паролей, которые имеют более широкий выбор воз­
можных символов, поэтому важно, чтобы пароли были длинными и состо ­
яли из различных символов, тогда злоумышленник не сможет угадать их
посредством многократного перебора.
Раскраска
7
в два цвета**
Граф -
это математический объект, состоящий из множества вершин
и множества ребер, попарно их соединяющих. На приведенном ниже графе
кружки представляют собой вершины, а линии соответствуют ребрам. Две
вершины, связанные ребром, называются соседними.
Раскрашивание графа заключается в присвоении цвета (синего, красного,
зеленого и т. д.) каждой его вершине таким образом, чтобы ни одна из двух
соседних вершин не имела одинакового цвета. Если количество доступных
цветов достаточно велико (например, равно количеству вершин в графе, ко­
торые необходимо раскрасить), то это, очевидно, очень просто . Но если ко­
личество цветов ограничено (например, всего три), то задача усложняется,
а в некоторых случаях становится невыполнимой . Можно легко начертить
граф с четырьмя вершинами и шестью ребрами, который тремя цветами рас­
красить нельзя.
В общем случае вопрос о k-цветной раскраске состоит в том, чтобы опре­
делить для любого графа, можно ли его раскрасить k цветами. Как это часто
бывает в информатике, существует алгоритм под названием исчерпываю­
щий поиск, который прекрасно работает в теории, однако на практике не­
применим, поскольку занимает слишком много времени, едва графы стано­
вятся большими. Он заключается в поочередном переборе всех возможных
k-цветных раскрасок, чтобы посмотреть, какая подходит. Для k ~ 3 вопрос
о существовании реализуемого на практике алгоритма k-цветной раскрас-
7. Раскраска в два цвета * *
ки относится к самому известному классу открытых задач в информатике,
называемых NР-полными задачами.
В этой головоломке мы предлагаем рассмотреть более простой случай
двухцветной раскраски, для которого существует эффективный и не очень
сложный алгоритм.
Задача к головоломке 7
Сможете ли вы написать на Python 3 программу, которая определяет,
возможно ли раскрасить любой заданный граф двумя цветами? Затем про­
тестируйте свою программу на графе выше и на графе ниже.
Решение на с. 121
't~ ~
~- i Компьютерное моделирование графа
В отличие от человека, программа не может работать непосредственно
с диаграммой. Поэтому первым делом необходимо определить компьютер­
ную модель графа. Ниже представлены два наиболее распространенных
подхода.
Граф может быть представлен матрицей смежности или списком вер­
шин и их соседей. Например, приведенный ниже граф может быть пред­
ставлен следующей матрицей смежности А:
0101
А= 1010
0101
1О 1О
Значение О в позиции i, j матрицы А означает, что ребро между вер­
шиной i и вершиной j отсутствует. Значение 1 означает, что ребро между
вершинами i и j существует. Например, 1 в третьей строке второго столбца
означает ребро, соединяющее вершины 3 и 2. То же самое относится и к 1 во
второй строке третьего столбца.
2. Головоломки
Другой метод моделирования графа состоит в том, что­
бы дать для каждой вершины список ее соседей. Приведен­
ный на иллюстрации рядом граф моделируется так: (1, (2, 4)),
(2, (1, 3)), (3, (2, 4)), (4, (1, 3)). Таким образом, (2, (1, 3)) озна­
чает, что вершины 1 и 3 соседствуют с вершиной 2. В зависи­
~
сЬ-сЬ
мости от выбранного подхода к моделированию, один и тот же
алгоритм приведет к созданию разных программ. В некоторых
случаях один подход оказывается предпочтительнее другого,
но иногда оба одинаково приемлемы.
@ для чеrо используются rрафы?
Графы повсеместно распространены в вычислительной технике и ис­
пользуются для моделирования многих реальных ситуаций, что позволя­
ет применять стандартные алгоритмы для решения повторяющихся задач.
Вот несколько примеров:
•
Сеть автомобильных или железных дорог можно представить в ви­
де графа, где вершины -
перекрестки, а ребра -
полосы движения,
с целью определения кратчайшего пути из одной точки в другую.
Это реализовано в GРS-навигаторах.
•
Телекоммуникационные сети также представляют в виде графов
для определения оптимальных маршрутов передачи цифровых па­
кетов данных.
•
Связи между веб- страницами в интернете образуют графы с мил­
лиардами вершин (веб-страниц) и ребер (гиперссылок). Знание
этой информации жизненно важно для многих компаний, а спо­
собы представления этих графов являются самостоятельной темой
исследования.
•
Еще одной задачей, в которой используются графы, можно назвать
знаменитую задачу о коммивояжере. Дается карта дорог и набор
пунктов назначения; задача состоит в том, чтобы найти маршрут,
позволяющий посетить каждый пункт ровно один раз, чтобы свес­
ти затраты на поездку к минимуму.
•
Графы используются также для моделирования связи между раз­
личными компонентами печатной платы. При этом ставится задача
минимизировать размер платы, обеспечив при этом отсутствие пе­
ресечения связующих проводников.
G
7. Раскраска в два цвета * *
@Для чего нужна раскраска графов?
Как это часто бывает в алгоритмах для графов, вопрос о k-цветной
раскраске, несмотря на его кажущуюся бесполезность, на самом деле
представляет собой абстрактную задачу, решив которую можно ответить
на целое семейство конкретных вопросов, примеры которых приведены
ниже .
•
Один из классических вопросов заключается в том, чтобы рассчи­
тать, сколько цветов необходимо для раскрашивания всех стран на
карте при условии, что две соседние страны должны быть разных
цветов. Эта задача, известная как «теорема о четырех красках» (че­
тыре -
минимальное значение, которое было предложено, но не до­
казано), была поставлена в 1850 году Фрэнсисом Гатри, затем в том
же году передана Августу де Моргану и наконец который поставил ее в
Артуру Кейли,
1878 году перед Лондонским математиче­
ским обществом.
•
Моделирование в виде графа предполагает представление каж­
дой страны в виде вершины, а границы между двумя страна­
ми -
в виде ребра между двумя соответствующими вершинами.
Таким образом, теорема о четырех красках становится задачей
четырехцветной раскраски графа определенного типа, представ­
ляющего собой географическую карту. Первое теоретическое до­
казательство теоремы с помощью компьютера было предложено
Аппелем и Хакеном только в 1976 году. А в 1995 году оно было
проверено и подтверждено Робертсоном, Сандером, Сеймуром
и Томасом.
•
Раскраска графов также используется при составлении распи­
сания выполнения заданий. В этой задаче работники должны
получить задания определенной продолжительности. Цель
минимизировать
количество работников.
пределить процессы по процессорам,
Также можно
-
рас­
минимизируя количество
производимых процессоров. Решение задачи сводится к раскрас­
ке графа: задание представляется вершиной, ребро между дву­
мя вершинами означает, что два связанных ребром задания не
могут
выполняться
одновременно,
а
цвета
ным работникам. Аналогичная задача -
соответствуют
раз­
распределение классов
в школьном расписании. Ее также можно представить как рас­
краску графа.
2. Головоломки
•
Последний пример -
распределение частот для мобильных телефо­
нов во избежание помех, связанных с местонахождением пользова­
телей. Эта задача тоже решается путем раскраски графа, в котором
пользователи мех, а частоты -
вершины, ребра -
места, где существует риск по­
цвета. В данном конкретном случае характерное
отличие заключается в том, что граф постоянно меняется, посколь­
ку пользователи перемещаются, а значит, решения должны непре­
рывно пересчитываться.
Электронное
8
голосование
**
Для проведения референдума в регионе Клермон-Ферран Министерство
электронного голосования решило обеспечить конфиденциальность выбора
участников с помощью известного и имеющего репутацию не подвержен­
ного взлому алгоритма шифрования RSA*. Для этого каждому избирателю
высылается открытый ключ шифрования (pk**) сервера голосования. Участ­
ники могут проголосовать «За», «Против» или «Воздержался». Они долж­
ны отправить свой зашифрованный этим ключом голос на сервер мини­
стерства. Зашифрованный голос Алисы был перехвачен и имеет значение:
229446820549265. Известно, что ключ pk равен:
(е, п)
= (806689751207077, 881856821380357).
Кодировка, выбранная для преобразования текста в число, работает сле­
дующим образом: каждая буква представлена последовательностью симво­
лов, состоящей из трех цифр в коде ASCII, приведенном на странице 65, затем
эти последовательности объединяются, и в итоге берется результирующее
целое число. Например, код слова Python выглядит так: 080 121 116 104 111
110, -
что дает целое число 80121116104111110. Для двузначных АSСП-ко­
дов, встречающихся внутри текста, таких как вторая буква Р в слове PyPhon,
необходимо оставить О слева от второй цифры, чтобы можно было декодиро ­
вать результат : 080 121 80 104 111 110 дает число 80121080104111110.
Задача к головоломке 8
Можете ли вы написать программу, позволяющую узнать, как проголосо­
вала Алиса?
Решение на с. 127
RSA ( буквенная аббревиатура от фамилий Rivest, Shamir и Adleman; криптосис­
Ш амира - Адлемана) - криптографический алгоритм с открытым
ключом . RSA стал первым алгоритмом такого типа, пригодным и для шифрования,
*
тема Ривеста -
и для цифровой подписи.
** От англ . puЬlic key -
«открытый ключ». -
Прим. ред.
2. Головоломки
~.,. \
.,._ , Модуnярная арифметика
В арифметике используются только целые числа. Дробные числа просто
не существуют.
В модулярной же арифметике сначала необходимо определить целое
число п, которое называется модулем, а затем производить все арифмети­
ческие вычисления по модулю п. Это означает, что результаты системати­
чески попадают в интервал [О; п - 1], который обозначается Z/ nZ, путем вы­
читания или прибавления п столько раз, сколько необходимо, как показано
на рисунке ниже при п
= 11.
+22.__ _ __ _
•
-14
О
1
2
3
4
5
6
7
8
9 10
13
Точно так же при евклидовом делении на п, которое должно быть це­
лым числом в диапазоне [О; п - 1], числа заменяются их остатком.
Этот оператор модуля, обозначаемый mod п, совместим с арифметиче­
скими операциями «+» и «х » , то есть в любой момент вычислений, соче­
тающих эти две операции, можно вернуться к Z/ nZ. Таким образом, числа,
с которыми можно работать, не являются произвольно большими. Это
отличается от обычной математики, но все еще довольно просто. Однако
данная математическая область огромна, и многие ее аспекты выходят за
рамки данной книги.
Расчеты RSA
Для генерации пары ключей RSA необходимо выбрать р и q личных простых числа
-
и вычислить их произведение п
емое модулем шифра. Далее вычисляется Ф(п)
два раз­
= р х q, называ­
= (р - 1) х (q - 1) -
так на­
зываемый показатель Эйлера для п, введенный швейцарским математиком
Леонардом Эйлером
(1707-1783 ). Остается только выбрать натуральное
число е, взаимно простое с Ф(п) и строго меньшее, чем Ф(п) *. Открытый
ключ RSA состоит из п и е.
*
Два целых числа являются взаимно простыми, если их единственный о бщий дели ­
тель равен 1. Например, 15 и 28 -
взаимно простые, а 15 и 21 -
0
нет.
8. Электронное голосование * *
Соответствующим секретным ключом будет натуральное число d, об­
ратное е mod Ф(п)*, которое также строго меньше Ф(п). Вычисление d может
быть эффективно выполнено с помощью расширенного алгоритма Евклида.
Сообщение М должно быть строго меньше модуля п. Поскольку вы­
числения при шифровании и дешифровании производятся по модулю п,
то расшифрованное сообщение является целым числом, строго меньшим
модуля п. Если для исходного сообщения М это не так, то оно не может
быть восстановлено в неизменном виде. М шифруется открытым ключом
(п, е) путем вычисления С= мemod п. Затем для расшифровки С с помощью
секретного ключа d необходимо выполнить вычисление М = 01 mod п.
Доказательство того, что исходное сообщение М действительно явля­
ется результатом операции дешифрования, основано на свойстве модуляр­
ной арифметики, известном еще с XVII в. как малая теорема Ферма и сфор­
мулированном Пьером де Ферма (1607-1685). В операциях шифрования
и дешифрования RSA используется возведение в степень, а числа, участ­
вующие в этих операциях, очень велики, поэтому важно, чтобы операции
выполнялись быстро. Для этого существует очень эффективный алгоритм,
называемый быстрым экспоненциальным алгоритмом.
Безопасность RSA
,1
Поскольку открытый ключ состоит из е и п, простые числа р и
узнать путем факторизации модуля п
Ф(п)
q можно
= р х q. Отсюда быстро вычисляется
= (р - 1)(q - 1), а затем и секретный ключ d, обратный е по модулю Ф(п).
Таким образом, безопасность шифрования RSA основана на том факте, что
еще не существует алгоритма, который мог бы эффективно разложить на
множители произведения больших взаимно простых чисел. По мере увели­
чения скорости работы процессоров для обеспечения безопасности шифро­
вания RSA требуются взаимно простые числа все большей величины. Ми­
нимальная длина ключей RSA, согласно требованию NIST** и ANSSI*** от
2020 года, составляет как минимум 2048 бит, а рекомендуемая - 4096 бит.
*
Два целых числа а и Ь являются обратными друг другу по модулю п, если их про­
изведение по модулю п равно 1, т. е. а х Ь = 1 mod п. Например, 3 и 9 являются обратными
друг другу по модулю 26, так как 3 х 9
модулю
= 27 = 1 mod 26. Число а имеет обратную величину по
n тогда и только тогда, когда а и п взаимн о просты.
** National Institute of Standards and Technology (Национальный институт стандартов
и технологий).
*** Agence nationale de la securite des systemes d'information (Национальное агентство
по безопасности информационных систем).
2. Головоломки
До 2004 года французское законодательство в области использования
криптографии было очень узким. В 1999 году был принят указ, разреша­
ющий использование 128-разрядных ключей, что было общепринятым на
тот момент, но применение более длинных ключей оставалось крайне огра­
ниченным. К счастью, закон 2004 года « О доверии в цифровой экономике»
в корне изменил ситуацию: в статье 30 было прописано, что «использова­
ние криптографии является свободным» . В частности, к изменению законо­
дательства привело развитие онлайн-торговли.
Наконец, необходимо понимать, что появление квантового компьюте­
ра, если оно произойдет, положит конец безопасности шифрования RSA.
В частности, алгоритм Шора, созданный в
1994 году Питером Уиллин­
стоном Шором (1959 г. р.) задолго до появления первого квантового ком­
пьютера, позволяет очень быстро разложить на множители произведение
двух взаимно простых чисел, даже очень больших. Другими словами, этот
квантовый алгоритм позволяет найти секретный ключ шифрования RSA
по открытому ключу. Он также позволяет взламывать шифры, основанные
на дискретных логарифмах, такие как шифр Эль Гамаля .
Асимметричная криптография и сложные задачи
В информатике сложной считается задача, которая при достаточно
больших параметрах не может быть решена за разумное время с учетом
текущей вычислительной мощности компьютеров. В криптографии пара­
метры безопасности соответствуют, например, количеству битов в ключе.
В этом контексте сложной задачу делает лишь тот факт, что мы не знаем
эффективного алгоритма ее решения .
При асимметричном шифровании существует математическая связь
между открытым ключом шифрования и секретным ключом дешифрова­
ния. Однако для обеспечения безопасности необходимо, чтобы секретный
ключ не мог быть выведен из общеизвестного открытого ключа. Другими
словами, если вычислить зашифрованное с помощью открытого ключа со­
общение легко, то вычислить открытое сообщение без секретного ключа,
используя только зашифрованное сообщение и открытый ключ, должно
быть трудно.
G
9
Биткоин
**
Биткоин был изобретен в 2009 году Сатоши Накамото . Это первая децен­
трализованная криптовалюта, то есть валюта, которая использует крипто­
графические примитивы для обеспечения своей безопасности и обходится
без централизованного управления.
Для осуществления платежа в биткоинах между двумя физическими ли­
цами люди, добровольно взявшие на себя роль банка и называемые майнера­
ми, должны решить своего рода математическую загадку, называемую хеш­
задачей: найти целое число п, при котором результат вычисления некоторой
хеш-функции Н на основе значения пи информации о транз акции обладал
бы определенным свойством.
В данной головоломке в качестве хеш-функции используется стандарт
SНА*, точнее, SНА-256. Для подтверждения транзакции, представленной
здесь суммой т, которую х передал у, требуется знание хеша предыдущей
транзакции, обозначенной р. Существуют и другие важные параметры, та­
кие как дата транзакции, но они в данной головоломке для простоты будут
проигнорированы. Наконец, задача хеширования состоит в том, чтобы найти
целое число п, чтобы:
Н(Н(хутрп)) меньше чем 2250
Хеш-функция SНА-256 принимает в качестве входных данных строку
символов, поэтому перед хешированием значения переменных х, у, т, р,
п
необходимо объединить (конкатенировать) .
Задача к головоломке 9
Алиса (х
= А) платит Бобу (у= В) 5 биткоинов (т = 5). Зная, что р рав­
но 42, может е ли вы вычислить наименьшее целое число п, при котором дан­
ная транзакция между Алисой и Бобом будет подтверждена?
Решение на с. 132
* Secure Hash Algorithm.
2. Головоломки
~ Криптоrрафическая хеш-функция
Криптографическая хеш-функция Н -
это функция, которая принима­
ет на вход любую последовательность битов произвольной длины, а воз­
вращает последовательность битов фиксированного размера, например
256 бит для функции SНА-256, которую можно представить в виде:
Н: {О, 1}* ➔ {О, 1}256, где множество всех битовых последовательностей
обозначается {О, 1}*.
Результат хеш-функции называется отпечатком, или хешем. В Python 3
библиотека Crypto . Hash позволяет использовать функцию SНА-256 со следу­
ющей командной строкой:
1
2
3
4
5
6
from Crypto .Hash import SHA256
h = SHA2 56. new ()
# Инициализирует h как отпечаток SHA-2 5б
m = ' HELLO'
h. update (m . encode (' UTF-8 ' ) )
hash = h. hexdigest()
print (hash)
#
Для этого необходимо с помощью команд pythonЗ
-m pip
install
pycryptodome==З . 4. 3 установить pycryptodome. В криптографии важно, чтобы
эта функция была устойчива к конфликтам, то есть вероятность нахожде­
ния двух разных сообщений х и х ', имеющих одинаковый хеш Н ( х) = Н ( х ' ) ,
должна быть пренебрежимо мала.
В
2012 году NIST стандартизировал хеш-функцию, дав ей название
Keccak, которая стала новым стандартом, известным как SНА-3.
Сиракузы**
10
Сиракузская последовательность определяется рекуррентно из началь­
ного целого числа u0 ~ 1 таким образом, что для всех п ~ О:
и /2 , если и четное
{
п+~
3u + 1 , если и нечетное
и
п
п
-
п
п
Иначе говоря, если число четное, то разделите его на два, а если нечетное,
то умножьте его на три и прибавьте единицу. В результате все равно получа­
ется целое число, с которым процедуру необходимо повторить.
= 7, следующие значения u = 22, и2 = 11, u = 34,
u = 17, u = 52, u = 26, u = 13, u = 40, u = 20, u = 10, u = 5, u = 16, u = 8,
И = 4, и = 2, и = 1, и = 4, и = 2, и = 1, и = 4 и т. д. Вычисления можно
14
15
19
20
16
17
18
Например, начиная с u0
4
5
6
7
1
8
10
9
3
11
12
13
продолжать, но значения стали периодическими, и цикл 1 - 4 - 2 повторяется
бесконечно.
При изменении начального значения u последовательность получаемых
0
значений, очевидно, будет другой.
Время полета целого числа u
0
-
это число п, количество шагов в вычис­
лении, через которое впервые получается значение а
= 1. Последующие зна­
чения всегда периодические, по циклу 1 - 4 - 2. Таким образом, время полета
числа 7 равно 16.
Максимальной высотой целого числа называется наибольшее число, по ­
лученное при его полете. Например, максимальная высота 7 равна 52.
Не существует общего метода, позволяющего заранее определить время
полета и максимальную высоту для данного целого числа. Например, время
полета 77 671 равно 231, а максимальная высота -
1 570 824 736. Аналогич­
но, последовательность, начинающаяся с числа 2 361 235 441 021 745 907 775,
имеет время полета 2284.
Задача к головоломке 1 О
Можете ли вы написать на Python 3 программу для вычисления наимень­
шего целого числа, время полета которого больше 100?
Решение на с. 13 7
2. Головоломки
Сиракузская гипотеза
Хотя сиракузская последовательность имеет очень простое определе­
ние, на сегодняшний день (2021 год) не существует математического дока­
зательства того, что последовательность, начинающаяся с любого значения,
через некоторое время всегда придет к 1, или даже того, что она обязатель­
но заканчивается циклом (возможно, отличным от 1 - 4 - 2). Ответ до сих
пор неизвестен, а значит, эта задача открытая.
С 1928 года, когда сиракузские последовательности были впервые ис­
следованы немецким математиком Лотаром Коллатцем, очень многие на­
чальные точки, которые были проверены, всегда давали последователь­
ность, заканчивающуюся значением 1, т. е. с конечным временем полета.
Сиракузская гипотеза, таким образом, утверждает, что этот вывод справед­
лив для любой точки отсчета, потому что наиболее вероятен. Данная гипо­
теза может однажды стать теоремой, если кому-то удастся ее доказать . При
условии, конечно, что кто-нибудь не докажет существование целых чисел
с бесконечным временем полета.
Сиракузская гипотеза также известна как гипотеза Коллатца, гипотеза
Улама, задача Какутани, гипотеза Туэйтса, алгоритм Хассе или даже задача
3х + 1. Название « сиракузская последовательность » не имеет отношения
ни к древнему городу Сиракузы на Сицилии, ни к современному городу,
расположенному на том же месте. Названа она так в связи с Сиракьюсским
университетом в США, откуда в 1950-х годах и получила распространение
среди математиков.
G
11
Кривые Безье
**
Кривые Безье, введенные Пьером Безье, используются для кодирования
векторных изображений и применяются в САП*, синтезе изображений и от­
рисовке шрифтов.
Математическое определение этих кривых основано на специальных по­
линомах, называемых полиномами Бернштейна. Чаще всего используются
полиномы третьей степени, но из-за сложности они в этой книге не приво­
дятся.
Используемые здесь кривые Безье называются «квадратичными» (т. е.
задаются полиномами второй степени) и определяются тремя параметрами,
называемыми «контрольными точками»: начальной точкой А, конечной точ­
кой С и вспомогательной точкой В.
По трем точкам А, В и С необходимо построить кривую из точки А в точ­
ку С, касательную к прямым (АВ) и (ВС). Чтобы понять форму такой кривой,
представьте себе гибкий металлический провод между точками А и С, при­
тягиваемый магнитом, который находится в контрольной точке В. Чем бли­
же часть провода к магниту, тем сильнее он притягивается и деформируется
(рис. справа вверху на стр. 48).
Алгоритм геометрического построения кривых Безье, представленный
в данной головоломке, может быть унифицирован для кривых более высокой
степени.
Для построения кривой Безье по контрольным точкам А, В и С достаточно
начать с замены ломаной линии АВС на две ломаные линии ADF и FEC, где:
•
D -
середина отрезка [АВ],
•
Е-
середина отрезка [ВС],
•
F- середина отрезка [DE].
Заметим, что D и Е -
вспомогательные точки, а F -
точка на искомой
кривой (рис. слева).
* Система автоматизированного проектирования (от англ. CAD, Computer-aided
design).
G
2. Головоломки
в
в
Е
о
•
с
А
с
А
Затем этот процесс необходимо повторить для двух новых ломаных ли­
ний -
ADF и FEC. После многих итераций в результате получается гладкая
кривая, проходящая через точки А и С и касательная к линиям (АВ) и (ВС)
(см. рис. вверху справа).
На практике для получения удовлетворительного приближения требует­
ся всего несколько итераций, как показано на рисунках ниже, полученных
с помощью двух, а затем трех итераций.
в
в
•
А
•
А
Задача к головоломке 11
Используя библиотеку turtle, можете ли вы написать программу для по­
строения квадратичных кривых Безье по трем контрольным точкам? Для
решения головоломки используйте тройки точек, приведенные ниже.
Решение на с. 150
1 = (40; 80), в 1 = (О; 10), с 1 = (60; 30)
А = (30; о), в = (40; 30), с = (50; 60)
2
2
2
А = (70; 60), В = (100; 80), С = (80; 40)
3
3
3
А4 = (ВО; 40), В4 = (70; 20), С4 = ооо; 30)
А
11 . Кривые Безье
**
Библиотека turtle в Python 3
В языке Python 3 имеется специализированная библиотека turtle. До­
кументацию по ней можно найти здесь: https://docs.python.org/fr/3/library/
turtle.html.
Как любую другую библиотеку Python 3, ее загружают, используя стро­
turtle import * в начале программы. Для работы
с графикой, прозрачной для пользователя, используется библиотека tkint er,
ки import tur tle или from
которую, возможно, придется установить на компьютер.
Команды, предоставляемые этой библиотекой, предназначены для
управления на экране объектом под названием «черепашка», который поз­
воляет рисовать в графическом окне.
Для перемещения черепашки и рисования с ее помощью доступны следующие команды:
f orward () перемещает на заданное расстояние вперед;
backward () перемещает на заданное расстояние назад;
right () поворачивает вправо на заданный угол в градусах;
lef t () поворачивает влево на заданный угол в градусах;
goto () перемещает в позицию, заданную двумя координатами (точ­
ка (О;О) находится в центре графического окна);
pendown () приводит перо в положение для рисования;
penup () поднимает перо;
clear () стирает нарисованное.
Существует множество других команд, но для создания большин­
ства рисунков достаточно восьми перечисленных выше. В программе
1
продемонстрирован простой пример использования библиотеки turtle
в Python 3.
Программа перемещает черепашку с поднятым пером в точку (О;О),
опускает перо, затем перемещает черепашку в позицию (100;200) и подни­
мает перо.
Программа 1. Пример использования библиотеки turtle
1
2
3
4
5
6
from turtle import *
penup ()
goto(0 , 0)
pendown ()
6 goto (l00 , 200)
G
2. Головоломки
7 17 penup ()
~ ~ mai nloop ()
На рисунке показан результат: линия, проведенная между точками с ко­
ординатами (О;О) и (100;200). Черный треугольник -
это указатель чере­
пашки.
@черепашка LOGO
Свое
LOGO» -
название
библиотека
turtle
получила
в
честь
«черепашки
робота, управляемого с помощью известного обучающего языка
программирования LOGO, созданного Уолли Фёрзег и Сеймуром Пейпер­
том в 1967 году в MIT (Массачусетский технологический институт) . Инс­
трукции в этой библиотеке очень похожи на инструкции в LOGO.
Первоначально черепашка
LOGO использовалась в некоторых шко­
лах в 1970-х и 1980-х годах. Следует отметить, что роль черепашки иногда
исполнял и ребенок (или взрослый), стоящий на четвереньках, что стало
предвестником тенденции к обучению информатике без компьютеров,
сформулированной в начале 2000- х Тимом Беллом и его коллегами в Новой
Зеландии (см. https://www.csunplugged.org).
0
12
Во времена древних
греков**- - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - --=----- - -
Aisnc е dotnd motojmr n ' ettna oeisorr iut t toja !ore
rt rDt , dao oinajnsc ' no , daan eii . js s 'm Oagetnveso
an rnisrtes а qiasrus aaiodii netspss or , jne ga
tqem !euna nesiPd saajq rieuq е iucnn ioteo n nasadt evo
rqontauinoierersn totrp.n,aa isiojs.lu'o anCnqv , e ' ua
yiias sleaa or traptosiaor tsrtq t urd . ! ' ее ic
CT l or ' osnaer nistaast vio datndeir i ее !fdn fotmEin
encnts ieo rlrrtee tos r ruda !tmei se sJ , jo ' !
una ! jg i ! ееа r rJc . da ' r eiaoMssiio о signr , e , aq n
iujsns '' oooaqnnniu , i? al n oaPotnvunogai utis ?jeeq
omnuRupt 'ers ims lla desrto qontaurnoveteraz ti dr
е . ' adn.eiet . ss socti anroly or eai tmr r ' te !ado
r ' uqEratutiv ' voliseiela r sna m suroa sanvrsidaaiseii
o.esdn noe Jtn du , desr ovqaenauinnn ' scetaoor unr d
. erej asoc !i u ' sgreLoe sannot , su- а aj qj -' duedie i
ins mrs oeeign setsqtn uuestie , os qu mputaoaiepir se
со rqenl~u teuiq s ur qneabu ' ioea.sn v.onla . neai s sma
р ourlpisaua sipsaisa u.orts ntosMs ria dt , ide , ses i,
jl cge lre aaonnr is 'rer aineavvc aeoqqi ruusqe 'i u ,i
ае lju csecj ' u ' endnas ' oeiton е nnr utaatn iio pssrta
otosrn . r а ttidM.osea ro iCtnns ' ее ! а qs vput ааа isnc
Рис. 9 . Текст на французском языке, зашифрованный методом скиталы
Задача к головоломке 12
Текст на рис.
9 зашифрован с помощью метода скиталы. Учитывая,
что количество оборотов - целое число, сможете ли вы написать на языке
Python 3 программу для расшифровки этого сообщения на французском?
Решение на с. 159
0
2. Головоломки
~ Скитала
Скитала
-
продолговатый цилиндр,
использовавшийся древними
спартанцами для шифрования сообщений. Его также называют «жезлом
Плутарха». Чтобы зашифровать сообщение, необходимо сначала намотать
на цилиндр ленту, а затем написать на ней сообщение. После этого ленту
разматывают, тем самым получая зашифрованное сообщение. Буквы пере­
мешиваются, и текст становится нечитаемым. Длина окружности цилиндра
является одновременно и ключом шифрования, и ключом дешифрования.
Для расшифровки достаточно намотать ленту на цилиндр с такой же дли­
ной окружности, чтобы получить сообщение в исходном виде.
Рис. 1 О. Пример шифрования с помощью скиталы
Например, чтобы зашифровать цитату Нельсона Манделы JE NE PERDS
JAMAIS. SOIT JE GAGNE, SOIT J'APPRENDS («Я никогда не проигрываю.
Либо я выигрываю, либо учусь») на цилиндре с длиной окружности в 3 бук­
вы, сначала нужно написать ее без знаков препинания и пробелов в три
строки, как показано ниже.
JENEPERDSJAМA
ISSOITJEGAGNE
SOITJAPPRENDS
Каждый столбец текста соответствует одному витку ленты, и эти буквы
в зашифрованном варианте сообщения окажутся рядом. То есть при разма­
тывании ленты получаем следующий шифр:
JISESONSIEOTPIJETARJPDEPSGRJAEAGNMNDAES
0
12. Во времена древних греков
(
**
Нельсон Мандела (1918-2013)
Нельсон Мандела -
южноафриканский политический деятель. Был
одним из ведущих борцов против апартеида -
сегрегационной полити­
ческой системы, при которой вся власть в стране принадлежала белому
меньшинству. За свои идеи 27 лет провел в тюрьме. Выйдя на свобо­
ду в 1990 году, добился мирного прекращения режима апартеида и стал
первым чернокожим президентом « радужной страны »
-
многонацио­
нальной и демократической ЮАР. Он проводил политику национального
примирения между черными и белыми и в 1993 году был удостоен Нобе­
левской премии мира совместно с последним белым президентом ЮАР
Фредериком де Клерком, с которым вел переговоры о прекращении апар­
теида в 1990 году.
Рис. 11. Нельсон Мандела
0
Четверичное
13
де ево
Приведенное
выше
**
четверичное
дерево
(или
дерево
квадрантов)
в Python 3 представляется в виде списка (подробнее см. ниже). Обратите вни­
мание, что в данном случае переносы строк используются только для удоб­
ства чтения.
tree = [ [О , О , О , [1, О , О , О ] ] ,
[0 , 0, [0 , 1, 0, 0] , 0] ,
[0 , 0, 0, [[1 , 0, 1, 0] , [0 , 0, 1, 1] , 0, 0] ],
[0 , 0, [[0 , 0, 1, 1], [0 , 1, 0, 1] , 0, 0] , 0]]
Задача к головоломке 13
Сможете ли вы с помощью программы восстановить изображение, скры­
тое в этом четверичном дереве?
Решение на с. 165
Дерево квадрантов
Для кодирования изображений часто используется метод, включающий
в себя представление картинки в виде дерева. Для простоты предполагает­
ся, что изображения черно-белые, квадратные, со стороной 211 •
Представление изображения в виде дерева квадрантов основано на
двух принципах:
0
13. Четверичное дерево
•
**
полностью белый или полностью черный участок изображения
представляется исключительно своим цветом;
•
двухцветный участок изображения разбивается на четыре квадрата.
Для иллюстрации принципа построения дерева квадрантов будет ис­
пользовано изображение, приведенное ниже. Цвета обозначаются как
Б-
белый и Ч -
черный. Узловая точка с четырьмя ветвями обозначается
F(hg, hd, bd , bg) , где hg, hd, bg и bd представляют собой левое верхнее (1),
правое верхнее (2), правое нижнее (З) и левое нижнее (4) квадратные под­
изображения соответственно.
Это изображение не является ни полностью черным, ни полностью
белым, поэтому оно делится на четыре квадратных участка одинакового
размера. Первый участок слева вверху полностью белый, поэтому он бу­
дет представлен буквой Б. Второй участок справа вверху не является ни
полностью черным, ни полностью белым, поэтому он делится еще на че­
тыре квадрата одинакового размера. Из них квадраты 1, 2 и 4 одноцветные,
а третий двухцветный, поэтому он также будет разбит на четыре квадрата,
первый из которых -
черный. Третий квадрат большой картинки тоже со­
держит участки разных цветов. Разбиваем его на четыре квадрата, в первом
из которых пиксели 1 и 4 черные. Еще один черный пиксель -
квадрат 3
в третьем участке . Наконец, последний квадрат полностью черный и пото ­
му представлен буквой Ч. В итоге получаем следующее дерево, графическое
представление которого приведено ниже.
F(Б , F(Б , Б , F(Ч , Б , Б ,Б ) ,Ч) , F(F(Ч , Б , Б , Ч) , Б , F(Б , Б , Ч , Б) , Б ) , Ч)
•••
••
•••••
•••••
•••• , 2
•••• 4 3
■
---- 4 х 4
------ 2х2
- - - - - - - - 1 пиксель
0
14
Семь мостов
Кёнигсберга
***
В XVIII в. в бывшем прусском городе Кёнигсберге (ныне российский го­
род Калининград) существовало семь мостов, расположенных как показано
на карте ниже.
Рис. 12. Карта Кёнигсберга
Швейцарский математик Леонард Эйлер, посетив этот город, сформу­
лировал вопрос, ставший впоследствии классической задачей: существует
ли маршрут, позволяющий пройти по каждому из городских мостов один
и только один раз и вернуться в исходную точку?
Записи его размышлений над данной задачей легли в основу того, что со
второй половины ХХ в. стало называться теорией графов, которую в некото­
рых аспектах можно отнести как к математике, так и к информатике.
Пользуясь современной терминологией, можно сказать, что Эйлер
смоделировал свою задачу с помощью графа, вершинами которого служат
различные части города, а ребрами -
мосты. Таким образом, имеем граф,
изображенный слева на рис. 13, где остров представлен вершиной О, часть
города в верхней части рисунка ти рисунка -
вершиной В, часть города в нижней час­
вершиной Н, а часть города в правой части рисунка -
шиной П.
G
вер ­
14. Семь мостов Кёнигсберга
***
Рис. 13. Модель семи мостов Кёнигсберга
Такая модель называется мультиграфом, потому что у нее имеется по
два ребра между вершинами В и О, а также между вершинами Ни О. Чтобы
прийти к обычному графу и иметь возможность использовать стандартные
рассуждения для теории графов, нам достаточно добавить по дополнитель­
ной вершине на одно из ребер между вершинами В и О, а также на одно из
ребер между вершинами Ни О, как показано справа на рис. 13. Очевидно, что
ответ на поставленную задачу от этого преобразования не изменится.
Решение задачи Эйлера для любого заданного графа -
это нахождение
эйлеровой цепи (или эйлеровой экскурсии), то есть пути, который проходит
через все ребра один и только один раз и возвращается в начальную точку.
Перед тем как приступать к решению поставленной задачи, ее следует
разбить на две части. Первая часть не вызывает особой сложности и пред­
ставляет собой проверку существования эйлеровой цепи для данного графа.
Вторая часть -
это построение такой цепи, если она существует. Для первой
части, проведя несколько экспериментов на небольших графах, вы наверняка
обнаружите необходимое и достаточное условие существования эйлеровой
цепи, а затем составите простую программу для его проверки. А вот разра­
ботка и тем более программирование алгоритма построения эйлеровой цепи
представляют собой определенные трудности, оправдывая три звезды в заго­
ловке этой головоломки!
Задача к головоломке 14
Напишите на языке Python 3 две программы:
•
первая программа должна определять, существует ли эйлерова цепь
для данного графа;
•
вторая программа должна найти для данного графа эйлерову цепь, ес­
ли она существует.
0
2. Головоломки
Вы можете использовать написанные вами программы, чтобы решить
задачу о семи кёнигсберских мостах, хотя для такого маленького графа это
не так интересно. В качестве чуть более содержательного примера рассмот­
рите граф, приведенный ниже, и проверьте свои программы на нем.
Решение на с. 172
(
ЛеонардЭйnер (1707-1783)
Швейцарский математик и физик, внесший вклад в несколько областей
математики. В комплексном анализе его имя носит формула: еiтт
= -1. Также
он ввел в геометрию такие понятия, как «углы Эйлера», «прямая Эйлера»
и «круг Эйлера». Кроме того, ему принадлежит формула S -А+ F = 2, харак­
теризующая выпуклые многогранники, где S -
ребер, а F -
число вершин, А -
число
число граней. Он также оказал влияние на развитие арифмети­
ки, введя характеристику Эйлера, которая в наши дни используется, напри­
мер, при построении шифрования RSA. Наконец, он положил начало тео­
рии графов, сформулировав и решив задачу о семи кёнигсбергских мостах.
Рис. 14. Портрет Леонарда Эйлера кисти Якоба Эмануэля Хандманна (1753)
0
15
Точный счет
«Точный счет» -
***
это один из раундов телевизионной игры «Цифры и бук­
вы». Игроки наугад вытягивают шесть карточек, на которых могут быть чис­
ла от 1 до 10, а также числа 25, 50, 75 и 100. Далее случайным образом выби­
рается число от 101 до 999. Задача игроков состоит в том, чтобы получить это
число с помощью шести карточек, имеющихся в их распоряжении, применяя
сложение, вычитание, умножение и деление. Каждая из шести карточек мо­
жет быть использована только один раз, при этом использовать все шесть
карточек необязательно. Результаты промежуточных операций, являющиеся
целыми положительными числами, могут быть использованы в остальных
вычислениях, но тоже только один раз. Наконец, если участник не может до­
биться точного ответа, он старается максимально приблизиться к нему, полу­
чив число немного больше или немного меньше искомого. В случае равенства
полученного числа у разных участников, побеждает игрок, использовавший
наименьшее количество карточек. В игре используется 28 карточек, кото ­
рые распределяются следующим образом: двадцать карт, пронумерованных
от 1 до 10 (по две на каждое число), две карты с числом 25, две карты с чис­
лом 50, две карты с числом 75 и две карты с числом 100.
Задача к головоломке 15
Можете ли вы написать программу для поиска всех возможных решений,
используя шесть карточек и случайным образом выбранное число? Подход
с использованием абстрактного синтаксического дерева предложен в решении
на странице 181.
Для карточек [2, 3, 4, 5] и числа 49 получаем следующий список точных
решений:
* (5 + 2)) = 49
( (5 + 2) * (4 + 3)) = 49
( (4 + 3)
Для карточек [2, 4, 2, 10, 8, 100] и числа 583 получаем следующий список
точных решений :
* (100 - 2) ) - 10) / 2) = 583
((((100 - 2) * (8+4 )) - 10) / 2) = 583
((((8 + 4)
Для карточек [1 , 1, 8, 6, 8, 4] и числа 664 получаем следующий список точ­
ных решений:
G
2. Головоломки
(8* (((6+1) * (4+8))
(8* (( (4 + 8) * (6+1))
= 664
1)) = 664
1))
'1,,
-i- Абстрактное синтаксическое дерево
Абстрактное синтаксическое дерево (англ. AST, Abstract Syntax Tree) это дерево, используемое для представления вычислений. Листья представ­
ляют собой константы, а внутренние вершины -
выполняемые операции.
Приведем пример AST для следующего вычисления: (2 + 5) * (З + 4)
= 49.
Здесь возможны деревья с количеством листьев от 1 до 6. Выясним воз­
можное число деревьев, имея в своем распоряжении четыре арифметических
операции и комбинации не более чем шести карточек. Во-первых, есть шесть
деревьев с одним листом: это когда нужно использовать только одну карто­
чку и не производить никаких вычислений. Выбрав две карточки из шести
и применив одну из четырех операций (сложение, вычитание, умножение
и деление), можно получить 4(~) набора из пяти новых возможных значений
для комбинирования, где (l) обозначает биномиальный коэффициент (число
сочетаний k элементов из множества п), который равен
n!
. Для каждого
k!(n- k)!
из полученных деревьев остается пять карт: четыре неиспользованные и ре-
зультат, полученный при комбинировании двух других. По тем же сообра­
жениям достаточно выбрать две карты из пяти и применить к ним четыре
комбинации. Это дает 4(~)4(~). Далее остаются четыре карточки, из которых
можно построить
4(~)4(~)4(~) дерева, затем три и наконец две. Все эти воз­
можности необходимо сложить, тем самым получая общее число 3 516 066.
6+ 4(~) +
4(~Н~) + 4(~Н~Н1) + 4(~H~)4UH~)+
+4(~н~н1н~н~) = 3516066
0
3
Подсказки первого
1
уровня
-----~----
------------~--~--------
Головоломка 1. Аскет
*
Текст не содержит цифр.
Головоломка 2. Криптарифм
*
Не пытайтесь заставить компьютер думать, он для этого не предназначен .
С другой стороны, он хорошо и быстро считает.
Головоломка 3. Кулинарная лопатка
Блины и целые числа в данном случае -
*
одно и то же.
Головоломка 4. Шадоки считали
*
Четыре сезона этого сериала были бы пронумерованы «BU », «ZO», «MEU »,
«BU GA» соответственно.
Головоломка 5. Стеганография
*
Внимательно посмотрите на числа, определяющие цвет каждого пикселя
на изображении.
Головоломка 6. Скрытые каналы
*
Библиотека t irne дана здесь неслучайно.
Головоломка 7. Раскраска в два цвета
Поиск подходящей модели графа -
**
это первый шаг.
3. Подсказки ... на всякий случай
Головоломка 8. Электронное голосование
**
Начните с написания алгоритма шифрования RSA.
Головоломка 9. Биткоин
**
Дважды выполните цепочку функции SНА-256, обращая внимание на
форматы ввода и вывода библиотеки.
Головоломка 1 О. Сиракузы
**
Это необязательно, но рекурсивное определение последовательности мо­
жет навести вас на мысль о рекурсивном программировании для вычисления
ее членов.
И в качестве бонуса вторая подсказка: в Python 3 существует два способа
выполнения деления, а именно:« / » и« // ».
Головоломка 11. Кривые Безье
**
Хорошо бы начать с того, чтобы узнать, как построить среднюю точку
отрезка.
Головоломка 12. Во времена древних греков
**
Начните с предположения, что размер цилиндра вам уже известен, но оп­
ределите вы его позже. И не сомневайтесь в своём французском.
Головоломка 13. Четверичное дерево
**
Листья черные и белые, и это не случайно.
Головоломка 14. Семь мостов Кёнигсберга
* **
Запускайте вторую программу только в том случае, если первая гаранти­
рует, что граф является эйлеровым.
Головоломка 15. Точный счет
***
Просчитайте все возможности с одной операцией, затем с двумя и т. д.
2
Подсказки второго
уровня
-----~-------'
----------------------------
Головоломка 1. Аскет
*
Название головоломки должно вызвать ассоциацию с ASCII. ASCII рас­
шифровывается как American Standard Code for Information Interchange (Аме­
риканский стандартный код для обмена информацией).
@дsс11 и Unicode
Вся информация в компьютере: текст, звук, изображения и т. д. -
пред­
ставлена числами. Каждому символу присваивается числовое значение .
Одной из первых кодировок была ASCII, но она была 7-битной, содержала
в себе всего 128 символов -
латинский алфавит, цифры, знаки препина­
ния и некоторые служебные символы. Современный стандарт кодировки
Unicode поддерживает разнообразные алфавиты, в таблице ниже приведе­
ны коды Unicode для прописных и строчных русских букв.
Буква
Unicode
Буква
Unicode
А
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
р
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
Б
в
г
д
Е
ж
3
и
й
к
л
м
н
о
п
с
т
у
ф
х
ц
ч
ш
щ
ъ
ы
ь
э
ю
я
Буква
Unicode
Буква
Unicode
а
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
р
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
6
в
г
д
е
ж
3
и
й
к
л
м
н
о
п
с
т
у
ф
х
ц
ч
ш
щ
ъ
ы
ь
э
ю
я
3. Подсказки ... на всякий случай
Головоломка 2. Криптарифм
*
Разложение числа по основанию 1О, безусловно, вам поможет.
Основание 1О
Числа, используемые в повседневной жизни, записываются по основанию
10, то есть в десятичной позиционной системе счисления. Это означает, что
в числе используется десять символов (цифры О, 1, 2, 3, 4, 5, 6, 7, 8 и 9) и что
значение цифры зависит от ее положения в числе. Например, число 1234
можно разложить на 1 х 1000 + 2 х 100 + 3 х 10 + 4 х 1.
Головоломка 3. Кулинарная лопатка
*
Попробуйте, например, смоделировать поведение лопатки с помощью
функции, выстраивающей элементы массива, начиная с выбранного, в об­
ратном порядке.
Головоломка 4. Шадоки считали
*
Многих создателей шадоков уже нет с нами. Их голос замолк в BU MEU
MEU BU BU ZO году.
Головоломка S. Стеганография
*
Всегда ли белый на самом деле белый?
Головоломка б. Скрытые каналы
Поместить return (False) в цикл for -
*
не самая лучшая идея, которая мо­
жет прийти в голову составителю этой программы.
Головоломка 7. Раскраска в два цвета
**
Сплетни, например, передаются от соседа к соседу. Здесь так же.
Головоломка 8. Электронное голосование
Кодировать алгоритм дешифрования не нужно.
**
2. Подсказки второго уровня
Головоломка 9. Биткоин
**
Для понимания смысла задачи начните с расчета при п = О .
Головоломка 1 О. Сиракузы
**
Немного модифицировав функцию, вычисляющую для заданного началь­
ного числа член определенного ранга в сиракузской последовательности, вы
сможете написать функцию, вычисляющую время полета заданного числа.
Головоломка 11. Кривые Безье
**
Рекурсивный метод может помочь придумать элегантное решение.
Головоломка 12. Во времена древних греков
**
Вычислите позицию зашифрованного символа, который нужно помес­
тить в позицию п в расшифрованном тексте.
Евклидово деление
Это деление с делителем и остатком, изучаемое в начальной школе. Напри­
мер, деление 31 на 7 эквивалентно записи 31
= 7 х 4 + 3, так как на вопрос
«Сколько раз семь укладывается в тридцать один?» можно ответить: «Четы­
ре раза, и три останется».
Как это почти всегда бывает в информатике, нумерация начинается с О.
Таким образом, 33-я буква исходного текста -
это буква Р, которая находит ­
ся в позиции 32:
JENEPERDSJAMAISSOITJEGAGNESOITJAPPRENDS
Разделив 32 на 13 (количество букв в строках таблицы, использованной
для шифра), что дает 32 = 13 х 2 + 6, мы можем найти положение этой буквы
Р в таблице: она находится в строке 2 (третья строка) и в столбце 6 (седьмой
столбец).
JENEPERDSJAМA
ISSOITJEGAGNE
SOITJAPPRENDS
0
3. Подсказки ... на всякий случай
Поскольку каждый столбец таблицы состоит из трех букв, которые
в шифре идут подряд, то положение той же буквы Р в шифре вычисляется по
формуле 3 х 6 + 2 = 20.
JISESONSIEOTPIJETARJPDEPSGRJAEAGNMNDAES
Головоломка 13. Четверичное дерево
**
Какова высота дерева? Каково было бы количество листьев, если бы дере­
во достигло максимальной высоты на всех ветвях?
Головоломка 14. Семь мостов Кёнигсберга
Поиск циклов -
хорошая идея.
Головоломка 15. Точный счет
***
Число состояний велико, но не бесконечно.
0
***
3
Подсказки третьего
--------~---уровня
----------------------------
Головоломка 1. Аскет
*
В Python 3 функция chr () позволяет получить символ, закодированный
в ASCII заданным целым числом. Таким образом, chr (192 ) дает «А» , а chr (255)
дает «я» .
Инструкции по открытию текстового файла и пошаговому чтению его со­
держимого приведены в разделе 1.
Для этой головоломки элементами файла являются символьные строки,
такие как ' 192 ' или
' 255 ', разделенные пробелами .
Прежде чем мы сможем использовать функцию chr (), необходимо преоб­
разовать эти строки символов в целые числа. Сделать это позволяет функция
int (). Таким образом, int (' 192 ' ) преобразует строку символов ' 192 ' в целое
число 65.
Головоломка 2. Криптарифм
*
Используйте технику исчерпывающего поиска (англ. brute force -
«метод
грубой силы» ), которая з аключается в последовательной проверке всех воз­
можностей .
Головоломка 3. Кулинарная лопатка
*
Для начала найдите способ положить самый большой блин вниз , а затем
проделайте то же самое с оставшимися .
Головоломка 4. Шадоки считали
*
Шадокам было хорошо знакомо основание 4.
G
3. Подсказки ... на всякий случай
,~~
~- i Представление натуральных чисеn с основанием 4
Натуральными числами называют целые положительные числа и ноль:
ноль, один, два, три, четыре и т. д. Для того чтобы объяснить, как эти числа
представляются с основанием 4, полезно сначала обратиться к привычному
способу записи чисел, известному как десятичное представление.
Десятичная система, называемая также «записью по основанию 10»,
является нашей повседневной системой представления чисел. Это пози­
ционная система счисления, то есть значение цифры зависит от ее поло­
жения в числе: единица, десяток, сотня и т. д. Считать по основанию 10
означает,
прежде всего, использовать десять символов для записи чи­
сел, т. е. цифры от О до 9. Сам счет ведется по десяткам, то есть каждая
цифра в числе ассоциируется с числом, равным десяти в определенной
степени, в зависимости от ее положения. Например, целое число 2345
состоит из:
•
•
•
•
пяти единиц;
четырех десятков (десяток -
это набор из десяти единиц);
трех сотен (сотня содержит десять наборов по десять единиц);
двух тысяч (тысяча -
это десять наборов по десять наборов по де­
сять единиц).
Иначе говоря,
2345
2 х 1ООО + 3 х 100 + 4 х 1О + 5 х 1
2 х 10 х 10 х 10 + 3 х 10 х 10 + 4 х 10 + 5 х 1
2 х 103 + 3 х 102 + 4 х 1о 1 + 5 х 10°.
По определению, а 0 = 1 для любого числа а. Для представления числа
по основанию 4 используется всего четыре символа: О, 1, 2 и 3, но принцип
остается прежним: счет идет наборами по четыре. Это означает, что каж­
дая цифра в числе с основанием 4 ассоциируется со степенью числа четыре,
используя обычную систему записи слева направо. Таким образом, 3012 это число, состоящее из двух единиц, одной четверки (набор из четырех
единиц), нуля наборов по шестнадцать (четыре набора по четыре) и трех
наборов по шестьдесят четыре.
Шестьдесят четыре
Шестнадцать
Четыре
Один
3
о
1
2
0
3. Подсказки третьего уровня
Другими словами, возвращаясь к привычной системе счисления с ос­
нованием 1О:
3 Х 4 3 + О х 42 + 1 Х 4 1 + 2 Х 4°
Это дает (если заменить степени четверки на действительные значения):
3 х 64 +Ох 16 + 1 х 4 + 2 х 1 = 198
Таким образом, число, представленное в десятичной системе числом
198, в системе с основанием 4 будет представлено числом 3012. Именно по­
этому важно указывать, какое представление используется, если возможно
несколько вариантов: например, 1ООО по основанию 1О -
это одна тысяча,
а 1000 по основанию 4 - это шестьдесят четыре. А в случае основания 5 (ис­
пользуются пять цифр О, 1, 2, 3 и 4 с наборами по пять единиц) эта же тысяча
будет представлять 125 (пять наборов по пять наоборов по пять единиц).
Головоломка 5. Стеганография
*
После того как вы найдете последовательность битов, вам должно помочь
решение головоломки 1, а возможно, перед этим вам поможет решение голо­
воломки 4.
Головоломка 6. Скрытые каналы
Цель данной головоломки -
*
смоделировать так называемую атаку по
скрытым каналам, предназначенную для взлома PIN- кодов и основанную на
времени выполнения программы верификации.
Для того чтобы увеличить время выполнения программы, в каждый этап
цикла f or искусственно вводится одно секундная задержка. Этот эффект поз­
воляет представить и решить головоломку, не прибегая к сложным измери­
тельным инструментам. Более того, эта задержка создает и определенную
долю реализма, поскольку замедление работы программ проверки лоrина
и PIN- кода иногда действительно используется для уменьшения количества
возможностей, которые злоумышленник может опробовать за определенное
время. Очевидным следствием такого приема является увеличение времени,
необходимого для взлома PIN- кода пользователя традиционными методами,
например с помощью словарей PIN- кодов.
Головоломка 7. Раскраска в два цвета
Построить решение или не достичь его момент.
0
**
в этом заключается ключевой
3. Подсказки ... на всякий случай
Головоломка 8. Электронное голосование
**
Нет необходимости искать ключ дешифрования, но стоит заметить, что
шифрование RSA является детерминированным. Это должно вам помочь.
При детерминированном шифровании двойное шифрование одного и того
же сообщения одним и тем же ключом дает одно и то же зашифрованное
сообщение, тогда как вероятностный шифр дает разные зашифрованные со­
общения.
Головоломка 9. Биткоин
**
Протестируйте свою программу перед запуском, чтобы избежать пере­
грева компьютера, поскольку майнинг биткоинов требует много энергии.
Головоломка 1 О. Сиракузы
**
Чтобы найти ответ на головоломку, проведите исчерпывающий поиск,
надеясь, что он не займет слишком много времени.
Головоломка 11. Кривые Безье
**
Третьего порядка должно быть достаточно, чтобы решить головоломку.
Головоломка 12. Во времена древних греков
**
Для каждой позиции в исходном тексте можно вычислить номер строки
и номер столбца, в которых находится соответствующий символ в таблице
шифрования, и сделать вывод о том, где его искать в шифре.
Головоломка 13. Четверичное дерево
Разрезать изображение на четыре части -
**
хорошая идея для расположе­
ния его на четверичном дереве.
Головоломка 14. Семь мостов Кёнигсберга
* **
Объединение двух циклов, имеющих общую вершину, дает цикл.
Головоломка 15. Точный счет
***
Проверьте программу на примере с четырьмя карточками; от этого ком­
пьютер точно не перегреется. Затем проведите тестирование на нескольких
примерах, чтобы как следует проверить разные частные случаи.
G
4
1
~о Аскет*
Философскую основу свободного программного обеспечения я могу объяс­
нить тремя словами: свобода, равенство и братство. Свобода что пользователи свободны. Равенство одинаковыми свободами. Братство -
потому
потому что все они обладают
потому что мы призываем все на­
ше сообщество к сотрудничеству.
Ричард Столлман, Liberte, egalite, fraternite
(«Свобода, равенство, братство»), интервью в журнале
Programmez! («Программируйте!»), № 95, март 2007 года
Для расшифровки предложенного текста необходимо сначала понять,
что для обозначения каждого символа числом использован код
ASCII.
Соответствие для заглавных и строчных букв приведено в таблице на стра­
нице 65. Поэтому для декодирования необходимо поочередно взять каждую
числовую запись и заменить ее на соответствующий символ . Это можно сде­
лать и вручную, но работа окажется чересчур утомительной, так как текст
довольно длинный: 498 символов, включая пробелы (32 в АSСП - коде). Вот
отличный стимул для написания программы, которая выполнит эту работу
за вас!
Для декодирования предложенного текста программа на языке Python 3
должна открыть файл Enigmal.txt, последовательно прочитать элементы
(строки символов, разделенные пробелами) из него, преобразовать каж­
дый из них в целое число, затем перевести это целое число в символ с по­
мощью кода ASCII и, по мере выполнения, объединить все эти символы
в одну строковую переменную. В приведенной ниже программе 2 все вы­
числения выполняет строка 6, а остальные строки обрабатывают файл
и его содержимое. Необходимые функции Python 3 описаны в подсказке
третьего уровня к головоломке 1 на странице 69.
0
4. Решения
Программа 2. Декодирование ASCII
1
2
3
4
5
6
7
8
# # Открывает текстовый файл в режиме чтения и проходит его по строкам и по словам
result=""
file=open (' .. /Enigmes/Enigrnal .txt', ' r' )
for line in file:
for word in line.split() : ## Преобразование каждого слова в число , а затем в символ ASCII
result = result + chr (int (word))
print (result)
file .close()
'1.,,
-i- Решение rоnовоnомки
Расшифрованный текст выглядит следующим образом:
У каждого поколения есть свой философ, писатель или художник, ко­
торый захватывает и воплощает в себе идею времени. Иногда эти
философы получают признание при жизни, но чаще всего им прихо­
дится ждать, пока на них наложит свой отпечаток время. Незави­
симо от того, будет ли это признание немедленным или запоздалым,
эпоха отмечена этими людьми, выражающими свои идеалы в шепоте стихов или в грохоте политического движения. У нашего поколе­
ния есть философ. Он не художник и не писатель. Он программист.
Этими словами Лоренс Лессиг во вступлении к книге Free Software,
Free Society: The Selected Essays of Richard М. Stallman («Свободное ПО свободное общество: избранные эссе Ричарда М. Столлмана» ), GNU Press,
2002 год, описывает Ричарда Столлмана.
@ Ричард Стоnnман и свободное программное обеспечение
Ричард Столлман (1953 - н. в.), исследователь в области информатики
и искусственного интеллекта из Массачусетского технологического инс­
титута, считается отцом свободного программного обеспечения
(Free
Software). Он рассказывает, как в 1980 году у него возникли трудности
с использованием нового принтера, установленного в лаборатории. Он по­
пытался получить исходники программного обеспечения, чтобы внести
исправления, однако выяснилось, что исходнии недоступны, поскольку яв­
ляются собственностью компании-производителя.
G
1. Аскет
*
Это показалось Столлману неприемле­
мым и побудило его основать движение за
свободное программное обеспечение. Его
участники выступают за следующие четы­
ре базовые свободы.
•
Свобода О. Свобода использования
программного обеспечения в лю­
бых целях.
•
Свобода 1. Свобода изучить принцип
работы программы и адаптировать
Рис. 15. Ричард Столлман
ее под свои нужды, что обязательно требует доступа к исходному
коду.
•
Свобода 2. Свобода распространения копий программного обеспечения.
•
Свобода 3. Свобода доступа сообщества к модифицированным версиям.
В знак уважения к культуре настоящих программистов этот список на­
чинается с О, как и нумерация в большинстве языков программирования.
Четыре характеристики, которые делают программное обеспечение сво­
бодным, ясны и просты. По мнению Столлмана, их признание способствует
улучшению окружающего мира для всех и представляет собой настоящую
философию разума*.
В 1985 году он основал организацию FSF (Free Software Foundation**)
для продвижения свободного программного обеспечения и защиты прав
пользователей. Он также стоит за проектом GNU (GNU is Not Unix***) и со­
зданием лицензии GNU is Not Unix GPL (General PuЬlic License), которая
определяет отношения между авторами программ и их пользователями.
Эта лицензия основана на концепции авторского «лева», антиподе ав­
торского права. Существует множество известных и широко используемых
пакетов программ с открытым исходным кодом, таких как операционная
система GNU5 Linux, веб-браузер Mozilla Firefox, французский видеопле­
ер VLC Media Player, программа для обработки изображений GIMP (GNU
Image Manipulation Program), а также Inkscape, Audacity, Вlender, Handbrake,
LibreOffice и некоторые другие.
*
Книга, рассказыва ющая об этой истории, находится в свободном доступе по адре­
су http:/ /www.oreilly.com/openbook/freedom/ chO l.html.
** https://www.fsf.org.
***В 1970 году операционной системе было дано название Unics Information and Computing Service, позже превратившееся в Unix.
G
Uniplexed
4. Решения
Многие разработчики из движения
open-source* считают требова­
ние вирусности, закрепленное в четвертом правиле лицензии GPL, чрез­
мерным. Поэтому существуют другие лицензии, которые требуют, чтобы
всем был доступен исходный текст, но не его модифицированные версии.
Так, например, обстоит дело с лицензией PSFL (Python Software Foundation
License) для языка Python 3.
/" unicode
Первоначально, в 1960-х годах в США, в коде ASCII для кодирова­
ния прописных и строчных букв, пробелов, цифр, знаков препинания,
а также некоторых математических символов и непечатаемых знаков (та­
ких как табуляция, возврат каретки и т. д.) использовались целые числа
от О до 127, представленные в двоичном коде 7 битами. Позднее размер
кодов был расширен до 8 бит с 256 возможными значениями (у каждой
страны разными) для кодирования знаков, таких как е, fl или с, харак­
терных для некоторых европейских языков. Свидетельством этой эпохи
является стандарт ISO 8859-1, или Latin-1, который иногда используется
до сих пор. Однако вскоре стали очевидны две серьезные проблемы. Во­
первых, отсутствие согласованности между различными расширениями
кода ASCII создавало проблемы на международном уровне. Во-вторых,
не учитывались системы письма, не основанные на латинском алфавите.
Для устранения этих недостатков с 1990-х постепенно вводится систе­
ма кодирования, расширяющая стандарт ASCII. Она получила название
Unicode, и ее целью стало достижение универсальности и функциональ­
ной совместимости . В 2021 году в западных странах наиболее широко
используется версия UTF-8, в которой применяется кодировка перемен­
ного формата, сохраняющая совместимость с кодом ASCII. Для эконо­
мии места в памяти наиболее распространенные символы имеют более
короткие коды. В кодировке Unicode может быть представлено более
140 ООО различных символов.
* Open-source (англ. « открытый исходный код » ) -
категория программ, чей про ­
граммный код открыт для просмотра, изучения и изменения, например, с целью коллек -
тивной их доработки, заимствования для собственных проектов или исправления в них
ошибок.
0
1. Аскет
/
*
Типы (Types) в проrраммировании
В программировании понятие type используется для определения ха­
рактера значений переменных, данных и операторов. Одна и та же после­
довательность битов может представлять собой число, символ, цвет, звук
и т. д. Поэтому для корректной обработки данных необходимо учитывать
их тип.
В Python 3, в частности, есть тип str, который соответствует символь­
ным строкам, тип int, который соответствует целым числам, и тип float ,
который соответствует числам с плавающей запятой. В Python 3 для опре­
деления типа данных используется команда t уре , например, t уре ( ' bon j our' )
определяет, что ' bon j our' имеет тип str.
В некоторых языках, называемых языками с сильной типизацией, та­
ких как Python 3 или Java, сложить целое число и символьную строку не­
возможно, тогда как в языке С это возможно . Наличие сильной типизации
уменьшает проблемы во время выполнения программы. Например, в об­
ласти безопасности это предотвращает возможность атак на тип, когда
путаница между идентификаторами и ключами позволяет злоумышленни­
ку нарушить протокол.
/
Преобразование типов
В Python 3 существует возможность преобразования строк в целые чис­
ла. Это необходимо в первой головоломке и выполняется с помощью фун­
кции int () . В частности, эта функция преобразует считанную из входного
файла строку, например ' 65 ', в целое число 65, т. е. обработка выражения
int ( ' 65 ' ) возвращает значение 65. Описание функции int () выглядит сле­
дующим образом:
int : str_.int
Это означает, что на вход принимается значение типа str (символьная
строка) и, если это возможно, преобразуется в значение типа int (целое чис­
ло). Если это невозможно, то выдается сообщение об ошибке. Так, int ('К')
invalid literally for int () with base 10 : ' К ', то есть ' К '
не представляет собой целое число по основанию 10.
выдает ValueError :
G
4. Решения
Переrрузка оператора
Один и тот же оператор может использоваться для работы с несколь­
кими типами данных. Например, в Python 3 оператор «+» используется
как для сложения чисел, так и для объединения строк. Так, 40 + 2 дает 42,
а ' фото '
+ ' выставка ' -
' фотовыставка '. Оператор «+», который может интер­
претироваться по-разному в зависимости от типа операндов, называется
перегруженным. Однако сложение (или конкатенация) целого числа и сим­
вольной строки невозможно. Например, при обработке выражения 4О+ ' da у '
будет выдано сообщение об ошибке «TypeError:
unsupported oper and type (s)
for +: 'int ' and ' str ' », что означает невозможность сложения значений
двух разных типов.
/
Статическая и динамическая типизация
При запуске компьютерной программы необходимо указать типы ис­
пользуемых переменных, чтобы к ним применялись правильные методы
обработки . Присвоение каждой переменной типа называется типизаци­
ей. Она бывает статической, когда проверка типов выполняется во вре­
мя компиляции программы, и динамической, которая осуществляется по
мере выполнения программы. В Python 3 применяется динамическая типи­
зация: тип переменной проверяется каждый раз, когда ей присваивается
значение.
/
Полиморфизм типов
Некоторые языки программирования, такие как
OCaml (Objective
Categorical Abstract Machine Language), позволяют определять операторы,
оставляя используемые типы как можно более общими . Это называется по­
лиморфизмом типов. Например, двоичный оператор «+ » имеет следующую
сигнатуру: а х а
_, а , -
то есть принимает два значения одного и того же
типа а и выдает значение того же типа. При выполнении программы, со­
держащей сложение, этот общий тип а реализуется через конкретный тип,
такой как целочисленный тип (int) или тип с плавающей запятой (float ),
и оператор принимает значение, соответствующее сложению двух значений
этого типа .
0
1. Аскет
*
~~ Достигнутые цели
Эта головоломка позволяет ввести несколько важных понятий:
•
чтение данных из файла;
•
типы данных и преобразование типов;
•
кодирование информации;
•
манипулирование строками символов;
•
использование двух вложенных циклов for.
~--
~~ Кодирование текста в ASCII
Чтобы переделать это письмо, нам пришлось использовать стандарт­
ный американский код, который спас многих компьютерщиков. Про­
грамма 3 преобразует файл . txt, содержащий текст, в символьную строку,
состоящую из ASCII- кодов всех символов этого текста. Метод поочеред­
ного считывания символов из файла отличается от метода, используемо­
го в программе 2, которая извлекает из каждой строки группы символов,
разделенные пробелами. Кроме того, в программе кодирования исполь­
зуется функция ord (), которая преобразует символ в его АSСП-код. На­
пример,
ord ( ' А ' ) выдает целое число 192. Затем, чтобы включить это
число в строку result, его нужно преобразовать в str с помощью функ­
ции str () .
Программа 3. АSСll-кодирование
## Кодирование символов в текстовом файле в формате ASCII
2 # # Открытие прочитанного текстового файла с посимвольным выбором пути
3 file = open (' Complementl . txt', ' r ')
4 result = ""
5 character = file.read(l)
6 while character :
7
# # Кодирует каждый символ в ASCII и преобразует в строку символов
8
result = result + str (ord (character )) + " "
9
character = file . read(l)
10 print (result)
11 f ile . close ()
1
0
4. Решения
Работа цикла while основана на тонкости языка Python 3: пока перемен­
ная character действительно содержит символ, она интерпретируется как
булево значение true. С другой стороны, после последнего символа в фай­
ле вызов f ile . read (1) выдает пустую строку, интерпретируемую как булево
значение False, что позволяет завершить цикл. Чтобы добиться такого же
поведения, не прибегая к этому приему, просто замените while character : на
while len(character)>O :.
Раскладка компьютерной клавиатуры
Расположение клавиш на клавиатуре -
важный вопрос в компьютер­
ной технике. Стандарты QWERTY (английский) и AZERTY (французский)
были придуманы во времена пишущих машинок. Главной задачей было
расположить клавиши таким образом, чтобы рычажки с буквами при пе­
чати не сталкивались. В 1930-х годах Августом Двораком и Уильямом Дили
была предложена раскладка Dvorak, где буквы английского языка распреде­
лены по частоте употребления таким образом, чтобы обеспечить удобство
работы машинистки и избежать ее утомления. К сожалению, эта клавиату­
ра до сих пор редко используется. В 2003 году появилась клавиатура ВЕРО,
облегчающая ввод текста на французском языке. В 2006 году Шай Коулман
предложил раскладку Colemak для английского языка, считая ее менее за­
путанной для пользователей, чем QWERTY.
2
~о Криптарифм
*
Я люблю математику прежде всего за то, что в ней нет ничего челове­
ческого.
Бертран Рассел, письмо леди Оттолине Моррелл, март 1912 года
(
Генри Эрнест Дьюдени (1857-1930)
Эта
головоломка
была
предложена
Г. Э. Дьюдени в июле 1924 года в журнале The
Strand Magazine. Этот британский автор со­
здал множество книг- головоломок. В то время
у несчастных читателей журнала в распоря­
жении имелись только бумага, ручка и сме­
калка, так как компьютеры появились только
в 50-е годы, а доступными для широкой пуб­
лики они стали только в 1980- х.
Рис. 16. Генр и Эрн ест Дьюде н и
Для решения этой головоломки важно понимать, что в десятичном пред­
ставлении числа разбиваются на разряды, кратные степеням десяти. Напри­
мер, SEND представляет собой число S х 1000 + Е х 100 + N х 10 + D х 1. Осно­
вываясь на этом наблюдении и проделав то же самое для MORE и MONEY, можно
написать программу, которая перебирает все возможные варианты и каждый
раз проверяет, выполняется ли равенство SEND + MORE = MONEY. Для этого необ­
ходимо написать вложенные циклы for.
Более конкретно, в предлагаемом расчете фигурируют следующие буквы:
S, Е , N, D, М, О , R, У . Каждой букве в программе соответствует переменная,
которая может принимать любое значение от О до 9, кроме S и М, для кото­
рых значение О исключено. Таким образом, изначально программа состоит из
восьми вложенных циклов for. После того как каждой переменной присвоено
значение, необходимо вычислить значения чисел, з аписанных как SEND , MORE
и MONEY, и проверить равенство SEND
+ MORE = MONEY.
4. Решения
Программа 4. Наивный вариант
1 for S in range (l , 10) :
2
for Е in range (10) :
3
for N in range (lO )
4
for D in range (lO)
5
f or М in range (1, 1О)
6
for О in range (10) :
7
for R in range (lO)
8
for У in range (lO )
9
if ( (lOOO*S+ lOO*E+ lO*N+D)
10
+ (lOOO*M+ 100*0+ lO*R+E)
11
== (l OOOO*M+lOOO*O+lOO*N+lO*E+Y))
12
print ("SEND=",lOOO*S+lOO*E+lO*N+D)
13
print("MORE=", lOOO*M+lOO*O+lO*R+E)
14
print ("MONEY=",lOOOO*M+lOOO*O+lOO*N+lO*E+Y)
Выполнение программы, приведенной выше, занимает более минуты да­
же на современном компьютере. Это естественно, так как итоговая проверка
выполняется 9 х 10 х 10 х 10 х 9 х 10 х 10 х 10, то есть 81 млн ра з. Кроме того,
программа предлагает 155 решений, большинство из которых являются не­
верными, поскольку в них две разные буквы имеют одно и то же значение.
Для подсчета решений необходима переменная counter. В начале работы
она инициализируется как О, затем инкрементируется (другими словами, уве­
личивается на 1) при проверке каждого решения и в конце выполнения про­
граммы выводится на экран.
Для исправления двух обозначенных ошибок необходимо добавить не­
сколько проверок, позволяющих избежать совпадения значений у разных
букв. Программа 5 исключает неверные решения и ускоряет вычисления*.
Программа 5. Простой вариант
1
2
for S in range (l ,10) :
for Е in range (10) :
3
if (E!=S} :
4
for Nin range (lO)
if (N!=S) and (N!=E) :
for Din range (lO)
5
6
*
Для заключительного условия в конце цикла достаточно одного if. В данном при­
мере оператор искусственно повторяется, чтобы разбить длинную строчку и уместить ее
на странице книги.
0
2. Кри птарифм
*
if (D!=S) and (D!=E) and (D !=N) :
for М in range (l,10) :
if (M!=S) and (M!=E) and (M!=N) and (M!=D)
for О in range (lO) :
if (O !=S)and (O! =E)and (O!=N) and (O !=D) and (O!=M)
for Rin range (lO) :
if (R! =S) and (R!=E) and (R!=N) and (R !=D) and (R!=M)\
and (R!=O) :
for У in range (lO) :
if (Y !=S) and (Y !=E) and (Y! =N) and (Y !=D)
if (Y!=M) and (Y! =O) and (Y !=R) :
if ((lOOO*S+lOO*E+lO*N + D)
+ (1000*M+100*0+10*R+E)
== (10000*M+1000*0+100*N+1 0*E+Y ))
print ("SEND=", \
lOOO*S+lOO*E+lO*N+D)
print ("MORE=" , \
lOOO*M+lOO*O+lO*R+E)
print ("MONEY=", \
10000*M+1000*0+100*N\
+lO*E+Y)
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
На этот раз программа выдает единственное решение головоломки,
а именно S
= 9, Е = 5, N = 6, D = 7, М = 1, О = О, R = 8 и У = 2, то есть:
+
9567
1085
10652
Время выполнения второй программы значительно меньше, чем пер ­
вой, ведь теперь финальная проверка выполняется в общей сложности
9 х 9 х 8 х 7 х 6 х 5 х 4 х 3, то есть примерно 1,6 млн раз .
Оптимизировать решение можно и дальше, исключая неверные решения
на более раннем этапе. Для этого необходимо перебрать переменные в опре­
деленном порядке, чтобы можно было проверить, что У -
это сумма D плюс Е
по модулю 10, тогда 10 * N + Dплюс 10 * R + Е по модулю 100 -
это 10 * Е
+ У,
а 100 * Е + 1О * N + D + 100 * О + 1О * R + Е по модулю 1ООО - это 100 * N + 1О *
* Е + У , как это сделано в программе 6. Результат получается практически
4. Решения
мгновенно, з а несколько секунд, тогда как в первом варианте на это уходит
более минуты.
Вместо 10 х 9 х 8
= 720 итераций цикла для трех переменных У ,
D,
Е
программа сделает всего 72 итерации благодаря дополнительной проверке У,
которую можно осуществить с помощью небольшой программы на Python 3,
использующей переменную-счетчик. Это дает выигрыш в десять раз. Добав­
ление второй проверки уменьшает количество итераций с 3024 до 290. Нако­
нец, добавление третьей проверки уменьшает число итераций с 1450 до 183.
Это объясняет, почему данная программа работает гораздо быстрее преды­
дущей .
И наконец, число, соответствующее слову MONROE, -
106 805.
Программа б. Оптимальный вариант
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
for D in range (10) :
f or Е in range (1О ) :
if (E !=D) :
for У in range( lO)
if (Y !=D) and(Y! =E) and(Y== (E+D)%10 )
for N in range (10) :
if (N !=D) and (N !=Е ) and (N !=У)
for R in range (10) :
if (R !=D)and (R !=E)and (R !=Y)and (R!=N)\
and ( (lO*N+D+ lO*R+E) %100==10*Е+У) :
for О in range (lO) :
if (O!=D) and (O! =E) and (O! =Y) and (O !=N) and (O !=R) and\
((100*E+lO*N+D+100*0+10*R+E) %1000==100*N+lO*E+Y)
for S in range( l , 10) :
if (S !=D)and (S !=E) and (S!=Y) and( S!=N)and\
(S!=R) and( S!=O) :
for М in range (l, 10) :
if (M !=D) and (M !=E) and (M!=Y) and (M!=N)\
and (M!=R) :
if (M!=O) and (M!=S) and ((lOOO*S+lOO*E+
lO*N+D)+(lOOO*M+ 100*0+ lO*R+E)
== (lOOOO*M+ 1000*0+ lOO*N+ lO*E+Y) )
print ("SEND=" , lOOO*S+ lOO*E+ lO*N+D)
print ("MORE=" , lOOO*M+lOO*O+lO*R+E)
print ("MONEY=", lOOOO*M+lOOO*O+
lOO*N+ lO*E+Y)
2. Криптарифм *
'1,,
-j- Сложность алгоритмов
Три программы, написанные для решения этой головоломки, иллюст­
рируют понятие времени вычисления алгоритма. Вы наверняка заметили,
что вторая программа работает примерно в пятьдесят раз быстрее первой,
а третья -
почти в тысячу раз быстрее второй .
При изучении алгоритма важно априори оценить порядок времени
вычислений, которое потребуется для выполнения соответствующей про­
граммы. Этому посвящен раздел информатики, называемый вычислитель­
ной сложностью. Одна и та же задача, как правило, может быть решена не­
сколькими алгоритмами, а время их выполнения представляет собой один
из параметров, на который ориентируются программисты при выборе алго­
ритма. Так, если выполнение простейшего алгоритма может затянуться на
тысячелетия, то, пожалуй, лучше выбрать более сложный, но зато быстрый.
Время вычислений не может быть выражено в виде точной величины,
поскольку зависит,
например,
от
мощности
процессора
компьютера,
на
котором выполняется программа. Вместо этого оценивается количество
выполненных элементарных операций, что в меньшей степени зависит от
особенностей реализации и аппаратного обеспечения. Элементарной опе­
рацией в программе для решения данной головоломки служила проверка
запрашиваемого равенства.
Иногда наиболее важным фактором оказывается не время выполнения,
а объем памяти, необходимый для выполнения вычислений. В этом слу­
чае используется термин пространственная сложность, но суть почти не
меняется. Разница во многом зависит от используемого аппаратного обес­
печения, поэтому компьютер с большим объемом памяти будет работать
быстрее.
В общем случае время выполнения алгоритма, очевидно, зависит от
входных данных. Например, вот простая задача: вычислить сумму первых п
целых чисел 1 + 2 + 3 + ... + п. Решить ее можно двумя разными способами,
имеющими разную сложность.
Первый вариант заключается в выполнении цикла for от 1 доп и на­
коплении промежуточных результатов в переменной. В этом случае про­
грамма выполнит п сложений, и мы будем говорить, что время вычисления
линейно поп.
Во втором варианте используется формула Гаусса: сумма первых п це­
лых чисел равна n(n+l). Программа, использующая этот результат, будет вы2
полнять только три операции (сложение, умножение и деление), независимо от значения п. Ее сложность постоянна, так как не зависит от п.
0
4. Решения
~
PROLOG
Многие языки программирования, такие как С, Java и т. д., по своим
принципам схожи с Python. Это императивные языки, поскольку програм­
мы состоят из инструкций, которые должна выполнять машина. Однако
существуют языки, основанные на иных формах программирования. Одна
из таких форм -
ЛОГическое ПРОграммирование, к которому относится
язык PROLOG, созданный Аленом Кольмероэ и Филиппом Русселем в Мар­
селе в 1970 -х годах.
Вместо того чтобы приказывать машине, что и каким образом вычис­
лять, можно применить следующий принцип: описать ограничения задачи,
не говоря напрямую, как ее решить.
Логическое программирование позволяет эффективно решать такие
задачи, как криптарифмы, с помощью элегантных программ длиной всего
в несколько строк.
В языке PROLOG, например, программа записывается следующим об­
разом:
1
:- use_rnodule(library( ' clp/bounds ')).
2
3
4
5
sendrnore (Digits) :Digits = [S, E,N,D, M,O, R, У] ,
Digits in 0 .. 9,
6
7
S#\=0,
М#\=0 ,
8
9
10
11
12
all different (Digits) ,
l000*S + l00*E + l0*N + D
+ l000*M + 100*0 + l0*R + Е
#= l0000*M + 1000*0 + l00*N + l0*E + У,
label (Digits ).
В этой программе сначала указывается, что буквы представляют собой
целые числа от О до 9 (строки 4 и 5) и что S и М ненулевые (строки 6 и 7).
Затем указывается, что все переменные различны (строка 8), и указывается
связь между ними (строки 9, 10 и 11). Наконец, остается только попросить
PROLOG вывести на экран значения, удовлетворяющие всем этим ограни­
чениям (строка 12).
0
2. Криптарифм
*
Чтобы протестировать эту программу, зайдите на сайт https://swish.
swi-prolog.org/, где расположен онлайновый компилятор PROLOG, учеб­
ное пособие по языку и множество примеров. Вы также можете скачать не­
обходимое программное обеспечение для любой операционной системы.
(
Иоганн Гаусс (1777-1855)
Иоганн Карл Фридрих Гаусс -
немецкий матема­
тик, астроном и физик. Считается одним из величай­
ших математиков всех времен. В детстве был вундер­
киндом, поэтому в свое время его прозвали «принцем
математиков». Оказал огромное влияние на многие
области математики, включая теорию чисел, теорию
вероятности и геометрию. Помимо упомянутой выше
формулы Гаусса, можно упомянуть метод исключения
Гаусса, позволяющий решать системы линейных урав-
Рис.17. Иоганн Карл
нений, а также кривые Гаусса, представляющие собой
Фридрих Гаусс
распределение вероятностей, иначе называемое нормальным распределением.
(
Бертран Рассел (1872-1970)
Бертран Артур Уильям Рассел -
британский ло­
гик, математик и философ. Относится к числу осново­
положников современной логики. В 1901 году заложил
основы логики в книге «Принципы математики», на­
писанной в соавторстве с Альфредом Нортом Уайт­
хедом. В этой книге он ввел понятие протокольных
предложений и сформулировал парадокс Рассела, кото­
рый в простом изложении звучит следующим образом:
«принадлежит ли множество множеств, не принадле­
жащих самим себе, самим себе?» Это вопрос, на кото­
Рис.18. Бертран
рый нельзя ответить ни «да», ни «нет» . Работы Рассела
Рассел
вдохновили Курта Геделя. В 1950 году Рассел получил
Нобелевскую премию по литературе.
4. Решения
(
Курт Гедель (1906-1978)
Курт Гедель -
австрийский математик, наиболее
известный благодаря двум так называемым теоремам
о неполноте, сформулированным в 1931 году и привед­
шим к концептуально сложным результатам, имеющим
фундаментальное значение для информатики. Он по­
казал, что в любой формальной системе математиче­
ских вычислений, непротиворечивой для арифметики,
можно записать свойства, которые невозможно ни до­
казать, ни опровергнуть. Такие системы рассуждений
Рис. 19. Курт Гедель
называются неполными, поскольку в них отсутствуют
определенные свойства. Важно отметить, что этот ре­
зультат касается доказуемости свойств, а не их истин­
ности -
двух понятий, которые необходимо различать
в математической логике именно в силу существования
неполных систем.
Неполнота
Упрощенное представление о понятии неполноты можно дать, исполь­
зуя вместо математических свойств компьютерные программы, как показа­
но ниже.
Вычисление, выполняемое программой, можно рассматривать как де­
монстрацию результата этого же вычисления. Предположим, что сущест­
вует программа ТОЧНЫЙ ОТВЕТ, способная вычислять (и, следовательно,
демонстрировать), является ли предложение истинным или ложным, ни
разу не ошибившись, отвечая ПРАВДА или ЛОЖЬ, когда получает любое
предложение на вход. Предложение типа Геделя, приводящее программу
ТОЧНЫЙ ОТВЕТ к сбою, звучит так: «Программа ТОЧНЫЙ ОТВЕТ не оп­
ределит это предложение как ПРАВДУ».
Чтобы понять причину этого, необходимо проанализировать поведе­
ние программы ТОЧНЫЙ ОТВЕТ. Возможны два варианта:
•
Допустим, предложение «Программа ТОЧНЫЙ ОТВЕТ не опреде­
лит это предложение как ПРАВДУ» истинно. Тогда программа ТОЧ ­
НЫЙ ОТВЕТ должна ответить ПРАВДА, что противоречит смыслу
предложения, если предполагается, что оно истинно.
0
2. Криптарифм
•
*
Допустим, предложение «Программа ТОЧНЫЙ ОТВЕТ не опреде­
лит это предложение как ПРАВДУ» ложно. Тогда программа ТОЧ­
НЫЙ ОТВЕТ должна ответить ЛОЖЬ, что соответствует смыслу
предложения, которое на самом деле ложное.
Таким образом, эти рассуждения показывают, что программа ТОЧ­
НЫЙ ОТВЕТ не может сделать утверждение о данном предложении: она
не может продемонстрировать ни его истинность, ни его ложность. Иными
словами, это предложение не укладывается в формальную систему демон­
страции, представленную программой ТОЧНЫЙ ОТВЕТ. Человек же спо­
собен определить, что предложение истинно, благодаря предшествующим
рассуждениям, не относящимся непосредственно к работе программы.
@ парадокс лжеца
Читатель может справедливо заметить, что в сказанном выше есть на­
мек на парадокс лжеца, известный логикам со времен античности. А вот
очень симпатичная его версия, встречающаяся в романе «Дон Кихот» Ми­
геля де Сервантеса (1547-1616), изданном в Испании в XVII в.: «... и судят
они на основании закона, изданного владельцем реки, моста и всего по­
местья, каковой закон составлен таким образом: "Всякий, проходящий по
мосту через сию реку, долженствует объявить под присягою, куда и зачем
он идет, и кто скажет правду, тех пропускать, а кто солжет, тех без всякого снисхождения отправлять на находящуюся тут же виселицу и казнить
,,
.
С того времени, когда этот закон во всей своей строгости был обнародован,
многие успели пройти через мост, и как скоро судьи удостоверялись, что
прохожие говорят правду, то пропускали их. Но вот однажды некий чело­
век, приведенный к присяге, поклялся и сказал: он-де клянется, что пришел
затем, чтобы его вздернули вот на эту самую виселицу, и ни за чем другим.
Клятва сия привела судей в недоумение, и они сказали: "Если позволить
этому человеку беспрепятственно следовать дальше, то это будет значить,
что он нарушил клятву и согласно закону повинен смерти; если же мы его
повесим, то ведь он клялся, что пришел только затем, чтобы его вздернули
на эту виселицу, следственно, клятва его, выходит, не ложна, и на основа-
нии того же самого закона надлежит пропустить его
судьям с этим человеком, -
*
Пер. Н. М. Любимова.
". и
вот
<... > что делать
они до сих пор недоумевают и колеблются»*.
4. Решения
@~ Достигнутые цели
Эта головоломка знакомит с тремя важными понятиями в информа­
тике:
•
метод исчерпывающего поиска (или метод грубой силы), часто мед­
ленный и трудоемкий, но обладающий тем большим достоинством,
что гарантирует нахождение всех решений, если они есть, или дока­
зывает, что их нет;
•
сложность алгоритма, то есть оценка количества проведенных опе­
раций и, следовательно, повышение эффективности программ;
•
универсальность, которая означает написание программы для ре­
шения целого семейства задач, а не для ответа на один вопрос.
G
3
~о Кулинарная лопатка
Есть два способа создания программного обеспечения: первый -
*
сделать
его настолько простым, что в нем, очевидно, не будет недостатков,
и второй -
сделать его настолько сложным, что в нем не будет очевид­
ных недостатков. Первый способ гораздо сложнее.
Сэр Чарльз Энтони Ричард Хоар,
лекция на вручении премии Тьюринга, 1980 год.
Опубликована в журнале Communications of the АСМ 24 (2),
февраль 1981 года, с. 75-83
Один из возможных алгоритмов для упорядочивания стопки блинов при
помощи только лопатки выглядит следующим образом: лопатку подклады­
вают под самый большой блин, затем переворачиваюь всю стопку на лопатке
так, чтобы самый большой блин оказался на самом верху. Затем подкладыва­
ют лопатку под блинчик, находящийся в нижней части стопки, и снова пере­
ворачивают всю стопку, в результате чего самый большой блин оказывается
в конечном положении в нижней части стопки. Затем процесс повторяется,
исключая блины, которые уже находятся в конечном положении, пока стопка
не будет упорядочена. Итого для достижения желаемого результата процесс
необходимо повторить столько раз, сколько блинов в стопке.
Экспериментируя с этим алгоритмом на картонных блинах, можно уви­
деть, что если блин уже находится на своем окончательном месте (например,
если самый большой блин с самого начала находится в нижней части стоп­
ки), то два первых переворота, по сути, ничего не меняют. Люди, в отличие
от компьютеров, от бесполезных действий приходят в замешательство. С ал­
горитмической точки зрения такую ситуацию гораздо проще игнорировать,
даже если это означает выполнение нескольких ненужных манипуляций, чем
выделять ее в частный случай.
Для решения поставленной задачи необходимо смоделировать стопку
блинов: проще всего представить стопку блинов разного размера в виде спис ­
ка чисел, представляющих некоторую последовательность блинов разного
4. Решения
диаметра. Не теряя обобщающего характера модели, предположим, что эти
числа -
целые. Идея решения этой головоломки состоит в том, чтобы упо­
рядочить список целых чисел, например [5,4,9,6,2,7,4,1]: в вычислительной
технике такое действие называется сортировкой. При этом необходимо до­
пустить, например, что элемент списка с индексом О -
в данном случае 5 -
соответствует диаметру блина, изначально находящегося в нижней части
стопки.
В инструкции указано, что единственный доступный инструмент -
это
лопатка. Ее нужно подсунуть под блин и использовать для переворачивания
той части стопки блинов, которая находится сверху. Таким образом, второй
шаг -
смоделировать действие лопатки, то есть расставить элементы списка
целых чисел между заданной позицией х и концом списка в обратном по­
рядке. Например, если это проделать со следующим списком [5,4,9,6,2,7,4,1],
начиная с элемента с индексом 3, то результатом будет [5,4,9,l,4,7,2,6]. Эту
операцию в программе 7 выполняет функция turnover (stack, х) : она меняет
элемент на позиции х местами с последним элементом списка, затем элемент
на позиции х+ 1 -
с предпоследним элементом и т. д. Наконец, необходимо
найти наибольший блин в некоторой части стопки. За это отвечает функция
maximum (stack, k) : она вычисляет позицию наибольшего значения элементов
в списке между позицией k и концом списка. Например, позиция наибольше­
го элемента в списке [5,4,9,6,2,7,4,1] между индексом 3 и концом списка равна
5 - это число 7.
'1,,
-i- Моделирование действий лопатки
Программа 7 содержит:
•
функцию, возвращающую индекс максимума списка, начиная с не­
которого индекса, заданного в качестве параметра;
•
функцию, разворачивающую список, начинающийся с определен­
ного индекса;
•
функцию, которая сортирует блины.
Программа 7. Сортировка блинов
1
2
3
4
5
# # Линейно обходит список, начиная с индекса k<len (stack)
# # Выводит индекс наибольшего элемента в списке между индексом k и концом списка
def maximum(stack, k):
maximum = stack[k]
j =k
3. Кулинарная лопатка *
6
7
8
9
10
for i in range (k,len (stack)) :
if stack [ i ] > maximum:
maximum = stack[i]
j =i
return j
11
12 ## Разворачивает часть списка меJR;ду индексом k<len (stack) и концом списка
13 # # Модифицирует список за счет побочного эффекта
14 def turnover (stack, х) :
15
length = len (stack)
16
for i in range ((length-x)//2) :
17
temp = stack [x+i]
18
st ack [x+i] = stack [length-1-i]
19
stack [length-1-i] = temp
20
21 # # Сортирует блины в списке
22 ## Модифицирует список за счет побочного эффекта
23 def sort_crepe (stack) :
24
for i in range (len (stack)) :
25
j = maximum(stack, i)
26
turnover(stack, j)
27
turnover(stack, i)
28
29 pile = [7 , 6, 1, 3, 2, 8, 9, 5, 4]
30 print (pile)
31 sort_crepe (pile)
32 print (pile)
/
Побочный эффект
Это буквальный перевод английского выражения side effect. Более кор­
ректным переводом будет «вторичный эффект» .
Побочный эффект в функции -
это модификация глобально доступ­
ного значения, а также инструкции ввода или вывода. Поскольку в Python 3
основным эффектом функции является возврат значения с помощью опе­
ратора return, изменения глобального контекста выполнения программы за
счет выполнения другого типа оператора функции называются побочными
эффектами.
4. Решения
Списки в Python 3 -
это так называемые мутабельные объекты, то есть
могут быть изменены побочным эффектом функции, которой они переда­
ются в качестве параметра. Именно это и происходит в программе 7 на пре­
дыдущей странице в функциях turnover и sort _crepe.
~ Поразрядная сортировка
Поразрядная сортировка (или сортировка по основанию) -
это алго­
ритм, который использовался для построения автоматических сортиров­
щиков в начале ХХ в. Например, рассмотрим следующий список чисел: 11,
912, 26, 77, 42, 136, 666, 92. Поразрядная сортировка по основанию 10 для
этой последовательности приведена в таблице ниже. Первой операцией
является сортировка списка по разряду единиц. Затем полученный список
сортируют по разряду десятков, сохраняя при этом порядок следования
элементов с одинаковым разрядом единиц. Наконец, сортировку повторя­
ют по сотням.
Исходное состояние :
11 912 26 77 42 136 666 92
1191242 9226136 666 77
11 912 26 136 42 666 77 92
Конечное состояние :
11 26 42 77 92 136 666 912
@ вig Data
В 2022 году одной из главных задач в области IT является обработка
данных Big Data, связанных с развитием интернета и IoT (Internet ofThings,
«интернет вещей», т. е. объектов, связанных посредством Сети): объем
данных, производимых, собираемых и анализируемых государственными
и частными структурами, растет такими темпами, которые еще несколько
лет назад были немыслимы. Основные характеристики Вig Data представ­
лены пятью аспектами.
1. Объем . Объем производимых данных огромен в связи со стремитель­
ным ростом числа датчиков на бытовых подключенных объектах.
2. Разнообразие. Данные становятся все более богатыми и гетероген­
ными, создавая широкий спектр ресурсов, которые могут быть использова­
ны в различных контекстах.
G
3. Кулинарная лопатка *
3. Быстродействие. Скорость, с которой появляются данные, представ­
ляет собой новую проблему для их обработки в реальном времени. Более
того, это значительно увеличивает объем имеющихся данных.
4. Значимость. Многие компании, такие как Google, Facebook*, Amazon
и др., смогли использовать Big Data и извлечь из них выгоду.
5. Достоверность. Последний пункт касается подлинности собранных
данных и направлен на обеспечение их точности. Действительно, среди та­
кого массива данных, каким является Big Data, неудивительно обнаружить
ошибочные данные.
Каждый из этих пунктов сам по себе представляет собой сложную зада­
чу, а их сочетание делает ее решение еще более сложным.
Аnrоритмы сортировки
,1
Существует множество алгоритмов сортировки . На странице «Википе­
дии» ** перечислено более двадцати, помимо алгоритма обратной сорти­
ровки, используемого в данной головоломке. Принципы работы наиболее
распространенных алгоритмов сортировки представлены ниже.
•
Один из простейших алгоритмов сортировки -
тот, который при­
меняют некоторые картежники: они берут карты по одной и упоря­
дочивают по старшинству. Этот алгоритм известен как сортировка
вставкой: отталкиваясь от уже упорядоченного списка карт (при­
чем изначально пустого), каждая новая карта по очереди вставляет­
ся на свое место относительно уже имеющихся в списке карт.
•
Сортировка по максимуму определяет максимальное число из
списка сортируемых чисел и помещает его в конец списка, меняя
местами с числом, находящимся на последней позиции, затем вос­
производит эту операцию с оставшимися числами . Повторяя этот
процесс столько раз, сколько имеется чисел, можно отсортировать
их от наименьшего к наибольшему. Можно также сортировать спи­
сок, каждый раз находя минимальное число и меняя его местами
с числом, стоящим в начале списка: в этом случае производится сор­
тировка по минимуму.
•
Более быстрым алгоритмом сортировки по сравнению с двумя пре­
дыдущими является сортировка слиянием. Она основана на следу­
ющих двух нюансах.
*
Принадлежит организации Meta, которая признана экстремистской и запрещена
на территории РФ.
** https://ru.wikipedia.org/wiki/Алгоритм_сортировки.
0
4. Решения
Список из одной карточки является упорядоченным.
Два списка, каждый из которых уже упорядочен, легко объеди­
нить в упорядоченный список. Для этого достаточно сравнить
первую карточку в каждом списке, меньшую из них располо­
жить в новом списке и снова начать с того, что осталось от двух
ИСХОДНЫХ СПИСКОВ.
Таким образом, исходный список сначала разбивается на несколько од­
нокарточных списков, каждый из которых уже упорядочен. Упорядоченные
однокарточные списки объединяются в упорядоченные двухкарточные
списки . Те, в свою очередь, объединяются в упорядоченные списки из четы­
рех карт, и так далее, пока не останется только один список, который стал
упорядоченным.
•
Принцип пузырьковой сортировки заключается в том, чтобы прой­
ти по списку, меняя местами два последовательных элемента, если
они расположены в неправильном порядке, и повторять этот про­
цесс до тех пор, пока в ходе выполнения не будет произведено ни
одной замены. Таким образом список сортируется.
•
Разновидностью пузырьковой сортировки является шейкерная сор­
тировка, при которой вместо возврата в начало списка система вы­
полняет пробег в обратном направлении, меняя местами элементы,
стоящие не на своих местах.
1
Сложность алrоритмов сортировки
Не все алгоритмы одинаково эффективны. Одна из методик оценки их
эффективности заключается в том, чтобы изучить их поведение при боль­
шом размере входных данных. Речь идет о возможности асимптотического
сравнения алгоритмов. Для этого математик Эдмунд Георг Герман Ландау
ввел понятие «большое О». Таким образом, если алгоритм ведет себя как
линейная функция от п, он принадлежит к классу сложности О(п). Это поз­
воляет легко сравнивать различные алгоритмы. Некоторые алгоритмы сор­
тировки в наихудшем случае имеют сложность О(п 2), такие как, например,
сортировка по максимуму, пузырьковая сортировка или даже сортировка
вставкой, в то время как существуют алгоритмы, имеющие в среднем слож­
ность О(п log(n)). Речь идет о сортировке слиянием или быстрой сортиров­
ке. Показано, что оптимальная сложность алгоритмов сортировки сравне­
нием в наихудшем случае составляет О(п log(n)).
0
3. Кулинарная лопатка
*
Это одна из очень немногих задач в алгоритмике, для которой известна
оптимальная сложность. Все представленные примеры, за исключением по­
разрядной сортировки, являются сортировкой по сравнению, то есть дан­
ные алгоритмы основаны только на сравнении элементов списка.
(
Сэр Чарльз Энтони Ричард Хоар (1934 r. р.)
В 1962 году Хоар разработал алгоритм быстрой сор­
тировки (Quicksort), который считается самым распро­
страненным алгоритмом в мире . Идея этого алгоритма
заключается в том, чтобы выбрать элемент, называемый
опорным, и расположить его на своем окончательном
месте,
поместив
все
элементы
с
меньшим
значением
слева от него, а все элементы с большим значением -
Рис. 20. Тони Хоар
справа.
Затем остается проделать то же самое с элементами, расположенными
слева от опорного и справа от него. Более детально это работает следую­
щим образом:
•
выбрать случайным образом элемент р из числа сортируемых эле­
ментов. Этот элемент называется опорным;
•
разделить оставшиеся элементы на два списка: те, что меньше р,
и те, что больше;
•
отсортировать каждый из полученных списков по тому же алго­
ритму;
•
объединить два отсортированных списка, сложив их друг с другом
так, чтобы опорный элемент оказался между ними.
Алгоритм быстрой сортировки является вероятностным алгоритмом,
то есть при его выполнении происходит случайный выбор (для опорного
элемента), поэтому время выполнения зависит от этого выбора. Напри­
мер, если в качестве опорного элемента всегда выбирается крайний пра­
вый номер в списке, то эффективность алгоритма невысока, так как его
сложность составляет О(п 2). С другой стороны, если в качестве опорного
всегда выбирается средний элемент, то сложность алгоритма в среднем со­
ставляет О(п log(n)).
Тони Хоар также написал компилятор для языка Algol 60. Кроме того,
он создал логику Хоара, которая используется для проверки корректности
программ.
G
4. Решения
Этот метод позволяет формально доказать, что программа делает то,
что должна делать. Он также предложил формальный язык, известный
как CSP (Communicating Sequential Processes), который позволяет опре­
делить взаимодействие параллельных процессов и который стал источ­
ником вдохновения для многих других работ в области параллелизма.
В 1980 году за работу над языками программирования Хоар получил пре­
мию Тьюринrа.
/ " Премия Тьюринrа
Престижная премия Тьюринга, названная в честь Алана Тьюринга, од­
ного из основоположников информатики, вручается ежегодно с 1966 года.
Она считается эквивалентом Нобелевской премии в области информатики.
Помимо Тони Хоара, перечислим несколько других известных специали­
стов, получивших премию Тьюринга за свои работы: в 1968 году- Ричард
Хэмминr (системы автоматического кодирования, обнаружение и исправ­
ление ошибок); в 1969 году- Марвин Мински (искусственный интеллект);
в 1974 году -
Дональд Кнут ( анализ алгоритмов, проектирование языков
программирования); в 1982 году- Стивен Кук (сложность компьютерных
вычислений); в 1985 году та); в 1991 году -
Ричард Карп (теория алгоритмов, NР-полно­
Робин Милнер (системы формальных доказательств
«Логика вычислимых функций», язык программирования ML, вычисление
взаимодействующих систем); в 2000 году -
Эндрю Яо (теория вычисли­
мости, генерация псевдослучайных чисел, криптография, сложность свя­
зи); в 2002 году -
Рональд Л. Ривест, Ади Шамир и Леонард М. Адлеман
(криптография с открытым ключом и система RSA); в 2012 году -
Силь­
вио Микали и Шафи Голдвассер (криптология и проверка доказательств,
интерактивные системы доказательств); в 2013 году -
Лесли Лэмпорт
(распределенные и параллельные системы). Единственными французски­
ми лауреатами этой премии стали Джозеф Сифакис и Янн Лекун. Джозеф
Сифакис получил премию в 2007 году вместе с Эдмундом Кларком и Алле­
ном Эмерсоном за предложение метода перечисления и верификации мо­
делей (model checking). Янн Лекун получил ее в 2018 году вместе со своими
канадскими коллегами Йошуа Бенrио и Джеффри Хинтоном за концепту­
альные и технические прорывы в области искусственного интеллекта, бла­
годаря которым глубокие нейронные сети стали важнейшим компонентом
информатики.
3. Кулинарная лопатка *
~~ Достигнутые цели
Эта головоломка знакомит с некоторыми важными принципами про­
граммирования, такими как:
•
•
•
•
•
важность моделирования;
различие между человеком и компьютером;
использование функций в Python 3;
модификация списка с помощью побочных эффектов в Python 3;
алгоритмы сортировки, которые широко используются в информатике и являются основой преподавания алгоритмики.
Важность алгоритмов сортировки в нашей жизни не нуждается в допол­
нительной демонстрации: простейший запрос к любой поисковой системе
требует сортировки результатов. С точки зрения математики более важным
представляется вычисление медианы ряда значений, которое происходит
непосредственно на отсортированном списке. Для этого расчета существу­
ет менее эффективный наивный алгоритм, который заключается в последо­
вательном удалении из списка максимумов и минимумов, пока не останется
один или два элемента. Наконец, существует множество образовательных
ресурсов, посвященных сортировке. Например, на сайте Interstice* можно
посмотреть на примерах, как работает ряд алгоритмов сортировки. На сай­
те http://www.sorting-algorithms.com можно найти ссылки на оригинальные статьи о сложности алгоритмов сортировки и наглядное представле­
ние, позволяющее сравнить эффективность различных алгоритмов. А сайт
https://algorythmics.ms.sapientia.ro/ всерьез предлагает народные танцы,
основанные на алгоритмах сортировки.
*
https:// interstices.info/jcms/с_6973/les-algorithmes-de-tri ?hlText=tri.
4
/о Шадоки считали
*
Чем меньше мы пользуемся компьютером, тем меньше вероятность то­
го, что он выйдет из строя.
Жак Руксель, «Шадоки»
Для начала необходимо догадаться, что шадоки используют основание 4,
поскольку их система счисления состоит всего из четырех слов и, соответ­
ственно, четырех цифр: GA обозначает ноль (О в десятичной системе), BU -
единицу (1 в десятичной системе), ZO и MEU -
двойку (2 в десятичной системе)
тройку (3 в десятичной системе). А для обозначения четырех (4)
у шадоков цифры (слова) нет. Вместо этого они называют один набор из че­
тырех единиц и нуля: BU GA. То же самое происходит и в десятичной системе
счисления после 9: для обозначения десяти нет новой цифры, поэтому добав­
ляется новый разряд, означающий один набор из десятка единиц и нуля, то
есть 10. Далее идут двузначные числа до 99 (девять десятков и девять единиц),
после чего начинаются трехзначные: запись 100 означает десять наборов из
десятков (сто) и ноль единиц. При основании 4 двузначные числа доходят
только до MEU MEU (что соответствует 3 х 4 + 3
= 15), после чего начинаются
трехзначные: число 16 записывается как BU GA GA.
Поэтому первая задача данной головоломки -
написать программу для
перевода чисел с основанием 4 в числа с основанием 1О, т. е. в десятичную
систему счисления .
Алгоритм перевода чисел шадоков в десятичную систему счисления со­
стоит в замене каждой цифры шадоков на ее значение в десятичной системе
счисления, затем умножении ее на степень четверки, соответствующую ее
разряду в числе шадоков, и суммировании всех этих значений . Таким обра­
зом, число BU ZO MEU становится равным 1 х 42 + 2 х 4 1 + 3 х 4°
= 27.
В итоге получаем, что число BU MEU ZO MEU GA GA, переведенное в де­
сятичную систему счисления, равно 1968 -
это год выхода в эфир первого
сезона мультсериала.
Однако возникает дополнительная вычислительная трудность: числа
шадоков представляют собой строки символов, которые перед выполне-
4. Шадоки считали
*
нием вычислений необходимо перевести в числовую форму. В Python 3 это
можно без труда сделать с помощью словаря -
структуры данных, позво­
ляющей связывать з начения с ключами. Например, в программе 8 строка:
shadok2four=l "GA ": 0, "BU" :l , "ZO ": 2, "MEU" :3} создает словарь shadok2four,
который связывает значение О с ключом "GA", значение 1 - с ключом BU
и т. д. В результате выражение shadok2four [ "GA "] принимает значение О .
'1,,
-j- Система счисnения wадоков
Программа содержит две функции:
convshadokhum переводит число из шадокской системы счисления
в человеческую (десятичную) систему счисления и решает голово­
ломку;
convhumshadok выполняет обратную операцию, чтобы можно было
проверить другие примеры.
Программа 8. Перевод чисел шадоков в десятичную систему счисления
1
2
3
# # Перевод числа шадоков в десятичную систему
def convshadokhum (shadoknum) :
# # Словарь позволяет перевести цифры шадоков в общепринятые цифры
4
shadok2four=l"GA" :0, "BU" :1, "ZO" :2, "MEU" :3)
5
6
7
8
# # Метод spli t (« «) используется для помещения в список элементов символьной
# # строки, разделенных переданным в качестве параметра разделителем
# # Здесь разделителем служит пробел « «
9
shadokdigit = shadoknum .split(" ")
1О
long=len (shadokdigit)
11
14
# # ВНИМАНИЕ : старшей цифрой в числе является та , которая находится
# # слева , то есть элемент с индексом О в списке shadokdigi t ,
## поэтому степень 4 равна long-i -1, а не i
15
res=0
16
for i in range (long) :
17
18
res=res+shadok2four[shadokdigit[i]]*4**(long-i-1)
return res
12
13
19
2О
# # Преобразование десятичного числа в число шадоков
21
def convhumshadok (humnum) :
4. Решения
22
23
# # Словарь позволяет переводить привычные цифры в цифры шадоков
four2shadok=!0 :"GA" , l:"BU", 2:"ZO", 3:"МЕU")
24
## ВНИМАНИЕ : при таком способе преобразования числа получаются
## справа налево , поэтому конкатенация следующая
## four2shadok{digit]+" "+shadok, а не shadok+" "+four2shadok{digit ]
25
26
27
28
29
shadok='"'
while humnum!=0 :
30
31
32
33
34
digit=humnum%4
shadok=f our2shadok [digit] +" "+shadok
humnum=humnum//4
return shadok
35 secret = "BU MEU ZO MEU GA GA"
36 print (convshadokhum (secret))
37
38 numЬer=l968
39 print (convhumshadok (numЬer))
Алгоритм, используемый в функции convshadokhum, основан на исполь­
зовании евклидова деления на четыре. При этом числа, записанные по ос­
нованию 4, записываются справа налево (от младшего к старшему). Так,
для перевода числа 42 в число по основанию 4 необходимо выполнить ев­
клидово деление 42 на 4, что дает 42 = 4 х 1О + 2 (частное равно 1О, оста­
ток -
2). Единицы в числе шадоков - это остаток, т. е. ZO. Далее возьмем
частное и снова разделим его на 4, что даст 1О = 4 х 2 + 2 (частное равно 2,
остаток - 2). Число «десятков» (четверок) в числе шадоков по-прежнему
равно ZO. Следующее деление, 2 = 4 х О + 2, дает шадокскую цифру для
«сотен» (шестнадцати) - ZO, по остатку 2, после чего алгоритм останавли­
вается, так как с частным О от последнего деления уже никаких операций
произвести нельзя. Таким образом, десятичное число 42 у шадоков соот­
ветствует записи ZO ZO ZO. При евклидовом делении на 4 остаток обяза­
тельно является целым числом от О до 3, то есть цифрой по основанию 4,
что и обеспечивает работу алгоритма.
Существует и другой алгоритм преобразования оснований, который
выдает числа слева направо (от высокого к низ кому). Это так называемый
«жадный » алгоритм.
4. Шадоки считали
*
1Ш Двоичная и шестнадцатеричная системы
Основание 4 не имеет широкого применения в программировании.
С другой стороны, основания 2 и 16 распространены повсеместно .
Использование основания 2, или двоичного представления чисел, свя­
зано с работой электронных компонентов в компьютерах, в частности тран­
зисторов. В двоичном представлении существует только два значения -
О
и 1, которые называются битами (сокр. от англ. Ьinary digit). Поскольку
принцип представления чисел с любым основанием одинаков, 1О 1О 1О в дво­
ичной системе соответствует 1 х 25 + О х 24 + 1 х 23 + О х 22 + 1 х 21 + О х 2° =
= 32 + 8 + 2, или 42 в десятичной.
В некотором смысле двоичная система является естественным пред­
ставлением чисел в вычислительной технике. К сожалению, это не очень
удобное представление для человека, поскольку даже небольшие числа
включают в себя большое количество битов. Например, число 2021 в дво­
ичном виде записывается как 111111001 О 1. Поэтому компьютерщики часто
используют представление чисел с основанием 16, иначе говоря, в шестнад­
цатеричном формате: он компактнее двоичного, и прямые преобразования
из одного в другой очень просты.
В шестнадцатеричном представлении используются десять цифр О, 1, 2,
... , 9, а также дополнительные символы - первые шесть букв латинского
алфавита: А, В, С, D, Е и F - для значений от десяти до пятнадцати. Кро­
ме того, каждая шестнадцатеричная цифра соответствует четырем битам
в двоичной системе:
Двоичная
Шестнадцатеричная
Двоичная
Шестнадцатеричная
0000
0001
0010
0011
0100
0101
0110
011 1
о
1
2
3
4
5
6
7
1000
1001
1010
1011
1100
1101
111 О
1111
8
9
А
в
с
D
Е
F
Например, если разбить число 11111100101 на группы по четыре би­
та справа налево, то получится О 111 111 О О 1О 1 (добавляем О к самой левой
группе битов, чтобы получилась полная группа). Каждая группа из четырех
битов заменяется шестнадцатеричной цифрой, поэтому легко видеть, что
в шестнадцатеричном виде число 2021 записывается как 7Е5.
4. Решения
1
янв Счеты
Счеты -
это инструмент, который помогает в вычислениях. В различ­
ных формах он использовался на протяжении веков римлянами, китайца­
ми, русскими и японцами. На рис. 21 изображены китайские счеты с числом
6 302 715 408. Счеты такого типа до сих пор широко используются в Азии.
Рис. 21. Китайские счеты, «Британская энциклопедия» (1875)
Каждый столбец, начиная с правой стороны, представляет, соответ­
ственно, единицы, десятки, сотни и т. д. Поскольку на счетах этого типа
только пять шариков внизу и два вверху, может показаться, что в них ис­
пользуется не десятичная система. На самом деле «величина» нижних шари­
ков равна 1, а верхних -
5 (счеты, конечно же, используют в горизонталь­
ном положении, иначе шарики не будут держаться). Считаются те шарики,
которые находятся рядом с центральной горизонтальной перекладиной.
Таким образом, в представленном примере к цифре единиц 3 мы должны
добавить 5, что в итоге дает 8. Цифра десятков равна О, потому что рядом со
штангой нет шариков. Число сотен равно 4, число тысяч равно 5 и т. д.
Для подобных счетов существуют алгоритмы выполнения арифмети­
ческих действий (сложение, умножение, вычитание, деление). В этих алго­
ритмах используется второй шарик «величиной» 5 в каждом столбце. Неко­
торые умельцы способны производить вычисления на таких счетах так же
быстро, как и на электронном калькуляторе.
@ Биби-бинарная система счисления
Биби-бинарная система счисления, или система Биби, была изобретена
певцом Боби Лапуантом в 1968 году. Она представляет собой графическое
изображение шестнадцатеричных цифр и связывает с каждой из них слог,
подобно системе шадоков: НО, НА, НЕ, HI, ВО, ВА, ВЕ, BI, КО, КА, КЕ, KI,
DO, DA, DE, DI.
4. Шадоки считали
*
Ниже приведена таблица, описывающая эту систему представления чи­
сел, опубликованная в 1970 году в коллективной монографии «Нечелове­
ческий мозг».
Десятичная
о
Шестнадца-
о
1
1
2
2
3
3
5
5
4
4
6
6
7
7
8
8
9
9
10
11
12
А
в
с
13
D
14
Е
15
F
теричная
Двоичная
Способ
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
1О 1О 1О 11 О 1 О 1 О 1 О 1 11 11 11 1
о о о о
о о
о о
1 1 О 1 1 О 00 1 1 О 1 1 О о о 1 1 О 1 1 О о о 1 1 О 1 1
о
о о
о
считывания
Обозначение
о
l J
с
r n ,_; л l
Произношение
но
НА
HI
во
НЕ
ВА
ВЕ
В1
ко
""'
КА
u 1 )
L V и
КЕ
Од
К1
DO
DE
DI
Термин биби-бинарный (З раза «би») относится к тому факту, что
16 = 2(2) • Поскольку термин «бинарный» используется для основания 2, Бо­
би Лапуант предлагает называть «би-бинарным» основание 4 (поскольку
4 = 2 2) и, соответственно, «биби-бинарным» - основание 16, которое со­
кращенно называет «Биби». Например, 2022 год в системе Биби произно­
2
сится как BIDEBE.
@ Боби Лапуант (1922-1972)
Робер Лапуант, также известный как Боби Лапуант, -
французский
актер и автор-исполнитель, известен публике использованием каламбу­
ров, спунеризмов, аллитераций и других неожиданных приемов в текс­
тах своих песен. Снялся в фильме Франсуа Трюффо «Стреляйте в пиани­
ста», вышедшем в 1960 году, где исполнил две песни: «Авани и Фрамбуаз»
и «Марсель». Среди его главных хитов: « Геликон», «Твоя Кати тебя броси­
ла», «Лошадиная сосиска», «Поймет, кто может», « Смесь мелодий», «Труба
из туалета», «Мама-рыба», «Арагон и Кастиль» * -
и это лишь некоторые
из них.
Вот несколько примеров этих знаменитых каламбуров и словечек**.
•
На современном этапе развития нашей цивилизации лишь немно­
гие научились писать без ошибок.
•
От большой выгоды выгадаешь больше.
* https://www.ina.fr/ina-eclaire-actu/video/I04359557 /boby-lapointe-aragon-et-castille.
** Из книги Боби Лапуанта ВоЬу Lapointe: Integrale (Полное собрание сочинений
Боби Лапуанта), изд-во Domens EDS Pezenas, 2002 год.
4. Решения
(
Клод Пьеплю (1923-2006)
Клод Пьеплю -
французский актер, комик и юмо­
рист. Он озвучил рассказчика в мультипликационном
сериале о шадоках, и эта роль принесла ему большой
успех благодаря бесстрастному тону и незабываемой
фразе, с которой он произносил знаменитые изре­
чения шадоков, например такие, как «Лучше качать,
даже если ничего не происходит, чем рисковать, что
произойдет что-то худшее, если не качать».
Рис. 22. Клод Пьеплю
Он был награжден Орденом искусств и литературы, которого удостаи­
ваются «лица, отличившиеся своим творчеством в художественной или ли­
тературной области или вкладом, который они внесли в развитие искусства
и литературы во Франции и во всем мире».
~@- Достигнутые цели
В этой головоломке вводятся два понятия:
•
позиционная система счисления с различными основаниями и ал­
горитмы для перевода из одной системы в другую;
•
использование словаря в Python 3.
Двоичное представление чисел в программировании является одним из
основополагающих элементов компьютерной культуры. Именно поэтому
основные понятия и алгоритмы изменения основания чаще всего изучают­
ся в первые недели курсов информатики.
~о Стеганография
5
*
Забавно, как иногда вещи могут менять свой облик, если смотреть на
них с другой точки зрения, отличной от той, с которой мы их всегда
знали.
Мишель Трамбле, Contes pour buveurs attardes
(«Сказки для умственно отсталых пьющих»), 1966 год
/
Стеrаноrрафия
Стеганография (от др.-греч.
stegan6s, «скрытый, не пропускающий
ничего» и graphein, «писать») означает, что секретное сообщение просто
скрывается, но остается доступным для чтения тому, кто знает, как его
найти. В отличие от этого, в криптографии (также от др.-греч. kruptos,
«скрытый» и graphein, «писать») секретное сообщение недоступно напря­
мую: чтобы его прочитать, получатель должен выполнить более или менее
сложное преобразование в зависимости от используемой степени безо­
пасности.
[QJ Геродот (484-445 rоды до и. э.)
Геродот считается первым историком. В своей «Истории» он описывает
два метода стеганографии.
•
В книге VII, параграф 239 он пишет, что Демарат передает Ксерксу
тайное послание. Послание было сначала написано на деревянной
дощечке, а затем покрыто воском, чтобы дощечка казалась чистой
и могла быть передана незаметно.
4. Решения
•
В книге V, параграф 35 Геродот сообщает, что Гистией использует
раба для передачи послания своему зятю Аристагору. Он бреет го­
лову раба, наносит послание на кожу его головы и ждет, пока волосы
отрастут. Затем он отправляет раба Аристагору, которому остается
только снова побрить его голову, чтобы получить доступ к посла­
нию. Таким образом, раб может безопасно пронести послание свое­
го хозяина через вражеские укрепления.
Рис. 23. Геродот
В этих двух примерах секретные сообщения скрыты от посторонних
глаз , но их все равно может прочитать тот, кто знает, как их найти.
Другой распространенный пример маскировки секретных сообщений,
который легко осуществить в домашних условиях, -
использование невиди­
мых чернил, также известных как симпатические чернила. Эта техника приме­
нялась уже в I в. до н. э., о чем писал в своих трудах Плиний Старший. Для это­
го достаточно написать на свитке папируса (можно и на листе белой бумаги)
молочком растения Euphorbla Tithymalus (по-русски молочай, хотя на самом
деле подойдет и лимонный сок). После высыхания бумага становится чистой,
а текст -
невидимым. Чтобы увидеть его, достаточно слегка нагреть лист над
пламенем масляной лампы (или прокатать утюгом). Под воздействием тепла
как по волшебству проявится текст, написанный коричневым цветом.
Изображение в формате PNG, подобное тому, которое предлагается в дан­
ной головоломке, разделено на множество пикселей, каждый и з которых
имеет свой цвет, представленный четырьмя целыми числами от О до 255
(в двоичном виде -
от 00000000 до 11111111). Один из приемов сокрытия
сообщения в изображении заключается в том, что изменение младшего бита
числовых значений, связ анных с цветом, практически незаметно для челове­
ческого глаз а.
5. Стеганография
*
Например, два серых цвета, RGВ-коды которых в десятичном виде (для
простоты прозрачность а не учитываем) равны соответственно 165, 165, 165
и 164, 164, 164, неотличимы друг от друга (см. ниже). Эти два цвета отлича­
ются только последним битом каждой компоненты, так как 165 записывается
в двоичном виде как 10100101, а 164- как 10100100. Таким образом, в изобра­
жении можно скрыть текст, закодировав его в двоичном виде в младших битах
чисел, представляющих цвета пикселей изображения. Код позволяет увеличи­
вать или уменьшать количество серых цветов. Таким образом, текст остается
секретным для всех, кроме того, кто знает, где искать его на изображении.
Серый (165, 165, 165)
Серый (164, 164, 164)
Чтобы обнаружить текст, скрытый в изображении, необходимо сначала
перебрать все пиксели изображения и для каждого пикселя извлечь млад­
ший бит из каждого из четырех чисел, обозначающих его цвет. Длина полу­
ченной таким образом последовательности битов в четыре раза превышает
количество пикселей в изображении. Далее необходимо разделить эту после­
довательность битов на группы по 8 бит, каждая из которых после перевода
в десятичную систему будет соответствовать ASCII-коду символа в скрытом
тексте. Наконец, необходимо объединить полученные символы, чтобы найти
решение головоломки.
'1,,
-i- Выявnение скрытоrо текста
Просто изменив имя изображения, программа, приведенная на стр. 31
этой книги в тексте данной головоломки, позволяет получить доступ к зна­
чениям пикселей изображения с помощью библиотеки PIL в Python 3. По­
скольку формат изображения -
PNG, значение пикселя соответствует спис­
ку из четырех целых чисел от О до 255.
Чтобы извлечь младший бит из каждого из этих целых чисел, достаточ­
но отметить, что для нечетных чисел он равен 1, а для четных -
О. Если п -
целое число, то выражение n%
2 вычисляется как остаток от деления п на 2.
Для получения символа, соответствующего определенному ASCII- коду,
перед использованием функции chr (), как в решении головоломки 1 на стр. 76,
необходимо преобразовать каждую группу из 8 бит в число с основанием 10.
Такое преобразование из двоичной системы в десятичную можно за­
программировать подобно преобразованию чисел шадоков (записанных по
основанию 4) в десятичную систему счисления, как в решении головолом­
ки 4 со стр. 27 на стр. 102.
в
4. Решения
Именно такую роль играет функция b2d () в программе 9, которая пре­
образует двоичное число, представленное строкой символов, состоящей из
О и 1, в целое число по основанию 10.
Так, число, записанное в двоичном виде как 101010, соответствует 42
в десятичном, как показывает следующее вычисление:
1 х 25 + О х 24 + 1 х 23 + О х 22 + 1 х 2 1 + О х 2° = 25 + 23 + 21 = 32 + 8 + 2 = 42,
или с ПОМОЩЬЮ функции b2d( "101010")
= 42.
Наконец, поскольку текст, скрытый в изображении, достаточно длин­
ный, желательно не пытаться вывести его на экран с помощью команды
print (), а записать результат в файл. Для этого необходимо создать файл
в режиме записи с помощью команды f. open («SecretText . txt» , «w») , затем
записать каждый полученный символ с помощью команды f. wri te ( ... )
и, наконец, не забыть закрыть файл с помощью команды f. close () .
Программа 9. Отображение текста, скрытого в изображении
1
2
3
4
5
6
7
8
9
1О
11
12
from PIL import Image
# Функция, которая преобразует целое число из двоичного в десятичное
def b2d (Ьinary) :
length = len (Ыnary)
res = О
for i in range (length) :
res = res+int (Ьinary[i])*2**(length-i- l)
return res
# Открыть изображение и получить пиксели
png = Image .open (" .. /Enigmes/Enigme5.png")
pixels = png.getdata ()
13
14
15
16
# Одному пикселю соответствует 4 бита RGB альфа
ListBits = [0]*(len (pixels)*4)
i = О # Посчитать число битов
17
18 # Для всех пикселей восстановить битовую строку в соответствии с четностью значений пикселей
19 for rgb in pixels:
2О
Li stBits [i] = rgb [О] %2
21
i = i+l
5. Стеганография
22
23
*
ListBits[i] = rgb [1] %
2
i = i+l
ListBits[i] = rgb [2] %
2
i = i+l
ListBits[i] = rgb [3] %
2
24
25
26
27
28
i = i+ 1
29 # Вычисление количества символов в 8 битах
30 NbCar=len (ListBits)//8
31
32
# Создание файла для решения
33
34
35
36
37
f=open ("SecretText. txt" , "w")
for i in range (NbCar) :
38
рrint ( "Выполнение программы закончено, ответ в файле SecretText .txt")
# Запись текста посимвольно в 8 -битных диапазонах
f.write(chr (b2d(ListBits[8*i :B*(i +1)])))
f .close ()
Обратите внимание, что из-за большого размера из ображения рас­
чет
может
занять
несколько
десятков
секунд,
в
зависимости
от
ком­
пьютера, прежде чем в консоли появится последняя строка «Выпол­
нение
программы
из 5000 х 4981
закончено ... ». Более
точно,
изображение
состоит
= 24 905 ООО пикселей. Каждый пиксель скрывает 4 бита,
а 8 бит кодируют один символ, то есть такое изображение может скрыть
текст из 12 452 500 символов (включая пробелы, переносы строк и т. д. ).
Текст, выбранный для этой головоломки, более короткий -
всего около
125 ООО символов. Поэтому текст занимает т олько начало результирующе­
го файла, а остальная часть, не содержащая никакой информации, состоит
из бессмысленного набора символов.
При открытии файла SecretText.txt, созданного программой 9, находит­
ся решение головоломки: это начало « Рассуждения о методе» , знаменитого
философского текста, написанного в 1637 году Рене Декартом.
/
Преобразование цenoro числа в байты
Следующая команда преобразует целое число 42 в его представление
в байтах: ' О : 08Ь '. format (42 ). На выходе получается ' 00101010 '.
4. Решения
Эта команда используется для изменения формата целого числа, уста­
навливая двоичный формат не менее 8 бит (другими словами, байт) и добав­
ляя при необходимости нули слева. Аналогично, команда' О : 05d '. format (42)
возвращает значение ' 00042 ' , поскольку оно выводится в десятичном фор­
мате с не менее чем 5 разрядами. Обратите внимание, что полученный ре­
зультат во всех случаях представляет собой символьную строку.
(
Рене Декарт (1596-1650)
Французский математик, физик и философ Рене
Декарт наиболее известен своим знаменитым выска­
зыванием «Я мыслю, следовательно, я существую».
В математике он является одним из изобретателей
аналитической геометрии. Он ввел декартовы коор­
динаты, используемые для определения местоположе­
ния объектов на плоскости и в пространстве. В 1637
году он написал первое в Европе обобщение геомет­
рии и алгебры под названием «Геометрия». Он также
автор «Рассуждения о методе» -
великого произведе­
ния французской философии эпохи Просвещения.
.....n.'> . . "<.U:t>.L--'-',Цrt"o .... , _. . ~ .. - - - ...........
..... ..... . . . , _ ~ •o.l ~,. •••, - - ..1 , •••, ,•
..z-'--t..••··········-
,_!')Ц-;,:;~=- .f'.,:,,~, ,_;!,...·- -.1-,, _,. - ' - 4
Рис. 24. Рене Декарт
~~ Скрыть текст в изображении
Чтобы скрыть текст в изображении, необходимо проделать обратный
процесс: перевести текст в последовательность битов при помощи опреде­
ленной кодировки, а затем изменить значение каждой из четырех состав­
ляющих каждого пикселя так, чтобы его младший бит совпадал с битом из
исходного текста. Для этого достаточно изменить числовые значения на
плюс или минус единицу.
Если количество битов, полученных в результате кодирования текс­
та, в четыре раза превышает количество пикселей в изображении, то весь
текст в изображении скрыть не удастся. Если же, как в данной загадке, текст
короче того, что можно спрятать в изображении, то информацию будут со­
держать только первые пиксели, а оставшаяся часть изображения измене­
ниям не подвергнется.
в
5. Стеганография
Проrрамма 1О. Кодирование текста в изображении
1
2
3
4
5
6
7
8
9
1О
11
12
13
14
15
16
17
18
19
2О
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
fran PIL iпlX)rt Image
# Огкрыть изображение и определить его пиксели и размеры
png = Image.Cf)e!l("Python_logo_icon-white.png")
pixels = png.getdata ()
width, height = png.size
# Огкрыть скрываемый текст и сохранить его в переменной text
# Текст кодируется в В-разрядном двоичном вJЩе с использованием кода ASCII
file = Cf)eil (' Coщolement5. txt' , 'r' ) # Декартовы рассуждения о методе
text=""
while 1:
char = file. read (1)
if not char:
break
text = text + str ('!О :08bJ '.foIIDat(ord(char)))
length=len (text) # Число битов в тексте, переведенном в двоичный фор,~ат
index = О # Счетчик пикселей
i=О # Счетчик битов
# Вставка текста при условии, что изображение достаточно велико для его размещения
# На ка!!ЩЫЙ пиксель изображения будет приходиться 4 бита из текстовых символов
for k in range (length// 4) :
# Восстановить значение пикселя в v
v= [pixels [k] [О], pixels [k] [1] , pixels [k] [2] , pixels [k] [3]]
# Для каждого альфа-компонента RGB
for j in range (4) :
# Если значение бита текста не соответствует значению бита изображения, измените его на 1
if (v[j]%2==0 and int(text[i])=l) or (v[j]%2=1 and int (text[i])=0) :
# Будьте внимательны: чтобы не превысить 255, сдвигайте -1 вместо +1.
if v[j]>=255:
v[j]=v[j]-1
else:
v[j]=(v[j]+l)
*
4. Решения
37
i = i +1
# Определить положение пикселя на изображении
38
col = index %width
39
40
row = index // width
41
# Заменить пиксель в изображении
png.putpixel( (col, row) , tuple (v))
42
43
index = index + 1
44
45 png . save (' vstegano .png' )
46 print ( ' Файл vstegano .png успешно создан ' )
~~ Достиrнутые цепи
В этой головоломке рассмотрены следующие аспекты:
•
манипулирование изображениями в Python 3 с помощью библиоте­
ки PIL;
•
•
~~~
запись в текстовый файл в Python 3;
кодирование текста в двоичном коде с использованием кода ASCII.
б
~о Скрытые каналы
*
Большой Брат засоряет мозги всем одинаково. Моя догадка: он считал
себя очень умным -
точно так же, как и другие считают себя очень ум­
ными. Я говорю ей, чтобы она напечатала слово «пароль».
Чак Паланик, «Колыбельная »*
Анализ программы
checkpin показывает, что если какой-либо символ
в РIN -коде неверен, то функция сразу же возвращает значение False. Такой
способ проверки достоверности введенного пользователем PIN- кода эффек­
тивен, но позволяет злоумышленнику извлечь ценную информацию.
Кроме того, проверка каждого символа совершается с паузой в одну секун­
ду, что делает поиск методом грубой силы более медленным и, следовательно,
нецелесообразным. С другой стороны, такое различие во времени выполнения
в зависимости от частичной коррекции начала РIN-кода позволяет осущест­
вить так называемую атаку по «скрытым каналам» (англ. side channels). Впер­
вые такой тип атаки был описан криптографом Полом Кочером в 1996 году.
(
Поп Кочер (1973 r. р.)
В
1996 году разработал первую атаку на RSA по
скрытому каналу**·*** . Концепция таких атак заключа­
ется в использовании доступной атакующему информа­
ции, такой как время, энергия и электромагнитные вол­
ны, для выведения секретной информации. В данной
головоломке используется именно время вычислений.
Рис. 25. Пол Кочер
* Пер. Т. Покидаевой.
** Paul С. Kocher, Timing attacks on implementations of iffiehellman, rsa, dss, and
other systems, In Neal KoЬlitz, editor, Advances in Cryptology - CRYPTO '96, 16th Annual
International Cryptology Conference, Proceedings, volume 1109 of Lecture Notes in Computer
Science, pages 104- 113, Springer, 1996.
*** Paul С. Kocher, Joshua Jaffe, Benjamin Jun, Differential power analysis, In Michael J. Wiener,
editor, Advances in Cryptology - CRYPTO '99, 19th Annual International Cryptology Conference,
Proceedings, volume 1666 of Lecture Notes in Computer Science, pages 388-397, Springer, 1999.
в
4. Решения
Одним из решений, позволяющих избежать этих атак, является обес­
печение того, чтобы раскрываемые вспомогательные данные не содержали
информации, которая может быть использована наблюдателем. Простей­
ший способ добиться этого -
сделать так, чтобы каждая операция в про­
грамме занимала одинаковое время или потребляла одинаковое количество
электроэнергии. Одним из решений является добавление случайного шума
в каждую операцию, чтобы наблюдатель не мог сделать никаких полезных
для себя выводов.
'1,,
-i- Измерение времени выполнения
Используя время отклика, можно угадать первую цифру PIN- кода за
1О попыток. Для этого достаточно протестировать десять PIN- кодов, начи­
нающихся с О, 1, . .. , 9, за которыми следуют, например, пять нулей, и изме­
рить время с помощью checkpin. В том тесте, который занял больше всего
времени, будет найдена первая цифра PIN- кода. Повторив эту операцию
для всех цифр PIN- кода, можно не более чем за 60 тестов с уверенностью
найти PIN- код .
Программа 11. Взлом РIN-кода
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import tirne
import rnath
global password
def checkpassword(l) :
for i in range (len (password)) :
tirne .sleep(l)
if password[i] !=l[i]:
return (False)
return (True)
# Функция replace заменяет букву а в позиции pos в строке s на значение car
def replace (s, pos, car) :
return s [: pos] + car + s [pos+l : ]
password=input ("Введите РIN-код из 6 цифр от О до 9 для проверки : " )
6. Скрытые каналы *
# Инициализация решения в 000000
18
19 solution="OOOOOO"
20
# Для каждой из цифр РIN-кода определим значение, которое является самым
# медленным для угадывания цифр РIN-кода по очереди
for i in range (б):
21
22
23
24
n=O
25
26
27
# Отображает текущее решение для проверки хода обнаружения РIN-кода
print (solution)
# Для всех значений от О до 9
28
29
30
while (n<=9) :
# Время начала измерений
start = time.time()
31
# Тест решения с возможными значениями для следукщей цифры
32
33
34
35
36
37
38
39
40
test = checkpassword(replace(solution, i, str(n)))
# Измеряет время окончания
end = time.time()
# Рассчитывает время проверки
duration = end-start
# Если РIN-код найден, обновление решения
if test == True:
solution = replace(solution, i, str (n))
# Принудительный выход из цикла
n = 10
41
42
else:
43
# Если время больше, чем количество правильных цифр, то цифра правильная
if math.floor(temps)>i+l :
44
45
# Обновлено решение с найденной цифрой
46
solution = replace(solution, i, str (n))
47
48
# Принудительный выход из цикла для ускорения поиска
n=lO
else:
49
50
51
n=n+1
рrint ("Секретный код :",
solution)
При разработке программы следует учесть, что для проверки последней
цифры одного параметра времени недостаточно. Поэтому необходимо про­
верять все цифры до тех пор, пока программа checkpin не выдаст значение
True.
4. Решения
Эта тонкость также требует обновления переменной solution и выхода
из цикла путем установки п равным 10. Последний прием также ускоряет
работу программы при угадывании числа за счет анализа времени выпол­
нения: по сути, проверять оставшиеся значения нет смысла. Мораль: на
такие программы нужно охотиться, а группы программистов, обладающих
подобными вредными привычками, -
выслеживать.
~б;J Достиrнутые цепи
Эта головоломка затрагивает следующие понятия:
•
•
•
глобальная переменная для построения функции checkpin;
измерение времени с помощью библиотеки time;
манипулирование строками.
7
~о Раскраска
в два цвета
**
Любовь переливается, как детская книжка-раскраска.
Оливье Норек, «Код 93», 2013 год
Как объясняется на стр. 34, k-раскраска графа -
это классическая алго­
ритмическая задача, для которой в общем виде не существует эффективного
решения. С другой стороны, для более узкой задачи двухцветности существу­
ет простой и эффективный алгоритм, поскольку для определения того, явля­
ется ли граф двухцветным, достаточно один раз пройти по каждой вершине
и каждому ребру. Этот алгоритм и предлагается использовать для решения
данной головоломки.
Суть заключается в том, чтобы случайным образом присвоить вершине
один цвет (в данном случае просто число, например, 1 или 2), а ее соседям другой. Остается только распространить первый цвет на соседей соседей
и т. д. Таким образом, для двух последовательно расположенных вершин
всегда будут выбираться разные цвета. Если возникает конфликт, т. е. в ходе
процесса вершине присваиваются оба цвета одновременно, то граф не явля­
ется двухцветным. Если же процедура завершается без конфликта, то полу­
чается двухцветный граф. Это означает, что две соседние вершины никогда
не будут одного цвета. Сложность этого алгоритма линейна по сумме числа
вершин и числа ребер в графе, и он реализован в программе 12 ниже.
В этой программе для представления графа выбрана модель, построенная
в виде списка соседей. Точнее, вершины нумеруются от О , а граф состоит из
списка G, чей элемент с индексом i представляет собой список номеров сосе­
дей вершины i . Например, в следующем списке G= [ [1, 3, 2], [0 , 2] , [О , 1, 3] , [О , 2]]
элемент G[2] = [О , 1, 3] означает, что соседями вершины 2 являются вершины О ,
1 и 3. Реализовать этот алгоритм можно также, выбрав для моделирования
графов матрицу смежности или список ребер, тогда отдельные компоненты
программы будут отличаться.
4. Решения
'1,,
-'f- Алrоритм двухцветной раскраски
С практической точки зрения это «жадный» алгоритм , который реа­
лизуется путем инициализации заполненного нулями списка coloring, чья
длина соответствует количеству вершин в графе. Цвет первой вершины
устанавливается равным 1, и окраска выполняется путем обхода всех вер ­
шин . Для распространения окраски от вершины i достаточно пройтись по
списку G[ i ] ее соседей, проверяя отсутствие конфликтов и присваивая им
цвет, противоположный цвету i . Вычисления заканчиваются, когда каждая
вершина имеет свой цвет.
Программа 12. Двухцветная раскраска графа
1
2
3
4
5
6
7
8
9
1О
11
12
13
14
15
16
17
18
19
2О
21
22
23
24
25
26
def colored (G) :
# Установить цветность на О
coloring = []
for l in G:
coloring.append(O)
res = True
coloring [О] = 1 # Окраска первой вершины в 1
Lvisit = [] # Список посещенных вершин
# Распределение цвета
while (len (Lvisit) <len (G)) :
for i in range (len (coloring)) :
if coloring[i] !=О and (i not in Lvisit) :
next = i
Lvisit.append (next)
color = coloring[next]
vlist = G[next] # Список содержит соседей вершины i
for k in vlist :
с = coloring[k]
if color== 1:
if с == 1:
res = False # Конфликт цветов
else:
coloring[k] = 2
else:
if с == 2:
res = False # Конфликт цветов
7. Раскраска в два цвета * *
27
28
29
30
31
32
33
else:
coloring[k] = 1
# Если G- двухцветный, то раскраска, в противном случае выдается False
if res == True:
return (coloring)
else:
return (res)
34
# Граф представляет собой список соседей
35
36
37
38
Gl =[ [1 ,2], [0,2,4,5] , [0,1,3,4, 6] , [2,4] , [1,2,3,5,6] , [1 ,41 6, 7,8] , [2,4,5] , [5,8,9], [5, 7,9] , [7 ,8]]
print (colored(Gl))
G2 =[[1] , [О , 2, 4, 5] , [1, 3, 6] , [2, 4] , [1, 3, 6] , [1, 6, 7, 8] , [2, 4, 5] , [5, 9] , [5, 9] , [7, 8] ]
print (colored(G2))
Приведенный ниже граф моделируется списком Gl смежных вершин,
а следующий -
списком G2. Программа сообщает, что первый граф не
является двухцветным, а второй -
является. Кроме того, программа вы­
дает следующую раскраску: вершины О , 2, 4, 5 и 9 -
белые, остальные -
черные.
В описании алгоритма двухцветной раскраски фраза «если вершине од­
новременно присвоены оба цвета, то граф не является двухцветным» требует
некоторого пояснения . Действительно, априори нельзя сказать, что другая
4. Решения
раскраска, начиная с другой вершины, не позволила бы избежать этого кон­
фликта и не привела бы к корректной двухцветной раскраске. Чтобы понять
это предложение, необходимо сначала осознать, что циклический граф с не­
четным числом вершин, как на диаграмме ниже, двухцветным не является.
С другой стороны, циклический граф с четным числом вершин двухцветным
является, так как для этого достаточно чередовать цвета.
Возвращаясь к доказательству алгоритма, отметим, что вершина, для ко­
торой существует конфликт, например двухцветная вершина на диаграмме
ниже, имеет (как минимум) двух соседей, через которых она получает две
противоречивые инструкции по окраске. Каждый из этих соседей сам полу­
чил свой цвет от предыдущей вершины и т. д. Таким образом, начиная с про­
тиворечивой вершины, можно построить две цепочки, повторяющие процесс
окрашивания. На определенном этапе эти две цепочки обязательно встретят­
ся: возможно, в самой первой окрашенной вершине, а возможно, в вершине,
окрашенной позже. Поскольку цвета двух соседей конфликтующей вершины
различны (иначе конфликта не было бы), это означает, что длины двух цепо­
чек от их первой общей вершины не имеют одинаковой четности. Две цепоч ­
ки, их общая вершина и конфликтующая вершина образуют цикл нечетной
длины. Какой бы метод ни был выбран для попытки двухцветной раскраски
всего графа, наличие цикла нечетной длины не позволит добиться успеха, что
и завершает процесс.
@ смежный граф
Граф определяется совокупностью вершин и совокупностью
ребер, соединяющих эти вершины. Граф считается смежным,
если из любой вершины можно перейти в любую другую вер -
шину, используя только ребра графа. Например, следующий
граф смежным не является.
~ ы
7. Раскраска в два цвета * *
Задачи, решение которых машина Тьюринга находит за полиномиальное
время, относятся к классу сложности Р. Это означает, что существует алго­
ритм, который находит решение этой задачи за полиномиальное время. За­
дачи в классе сложности NP, полиномиальной недетерминированности, это задачи, для которых проверка решения возможна за полиномиальное
время . Это понятие было введено в 1917 году Стивеном Куком. Например,
задача о коммивояжере или трехцветная раскраска являются NР-задачами .
Проблема Р
=< NP - одна из наиболее важных гипотез в информатике. Это
одна из семи проблем премии тысячелетия, предложенной Математическим
институтом Клэя. Тому, кто решит хотя бы одну из них, обещано вознаграж­
дение в размере одного миллиона долларов. В 2022 году из семи предложен;,
ных проблем шесть остаются нерешенными, в том числе проблема Р= NP.
Задача о коммивояжере
Эта задача взята из реальной жизни. Она состо­
ит в том, чтобы помочь коммивояжеру организовать
поездку, маршрут которой начинается от его компании,
проходит
через
всех
клиентов
и
возвращается
в
ис­
ходную точку, причем дважды один и тот же город не
посещается. Это NР-трудная задача, формализованная
Уильямом Роуэном Гамильтоном (1805-1865). В теории
графов гамильтоновым называется путь, который про­
ходит через все вершины графа один и только один раз.
Рис.26. Уильям
Роуэн Гамильтон
Граф считается гамильтоновым, если существует гамильтонов путь, ко­
торый называется циклом. Например, граф, изобретенный в 1970 году Вац­
лавом Хваталом, показанный ниже, содержит 370 различных гамильтоновыхциклов.
4. Решения
~~ Достигнутые цели
Эта головоломка затрагивает следующие аспекты:
•
•
•
•
манипулирование списками в Python 3;
определение структуры данных для работы с графом;
просмотр графа;
раскрашивание графа в два цвета.
8
~о Электронное
голосование
**
Утверждать, что вас не волнует неприкосновенность частной жизни,
потому что вам нечего скрывать, ничем не отличается от утверждения,
что вас не волнует свобода слова, потому что вам нечего сказать.
Эдвард Сноуден, Reddit*, 21 мая 2015 года
В 2022 году шифрование RSA, считающееся надежным, стало самым рас­
пространенным в мире. В этой головоломке оно используется для гарантии
отсутствия сбоев во время выборов. Однако следует отметить, что RSA от­
носится к детерминированному шифрованию, то есть сообщение т, зашиф­
рованное с помощью заданного открытого ключа, всегда будет зашифровано
одинаково.
Таким образом, чтобы определить значение перехваченного голоса Али сы, нам достаточно сравнить его с шифрами трех возможных значений для
выборов. Поэтому для начала необходимо закодировать эти три значения,
а затем их зашифровать.
Используя функции encode и decode в программе 13, кодируем OUI (ЗА)
как 79085073, NON (ПРОТИВ) как 78079078 и BLANC (ВОЗДЕРЖАЛСЯ)
как 66076065078067. Затем шифруем каждое из этих чисел открытым ключом
(е, п)
= (15213133, 881856821380357) и сравниваем полученные результаты
с перехваченным значением .
Зашифрованный бюллетень OUI (ЗА) равен 435621141398543, зашифро­
ванный бюллетень NON (ПРОТИВ) -
229446820549265, а зашифрованный
бюллетень BLANC (ВОЗДЕРЖАЛСЯ) - 512998179758979. Таким образом,
Алиса проголосовала против.
* https:/ /www.reddit.com/ r /IAmA/ comments/ 36ru89 / just_days_left_to_kill_mass_
surveillance_under/crglgh2/.
4. Решения
'1,,
-'f- Кодирование, декодирование и шифрование
Программа 13 содержит функции encode и decode, которые используют
код ASCII для кодирования сообщения в виде целого числа и декодирова­
ния целого числа в виде сообщения. Остальная часть кода используется для
построения функции шифрования. Для этого необходимо вычислить мо­
дульную экспоненту.
Программа 13. RSА-шифрование
1
2
3
4
5
6
7
8
import random
# Кодирует текст в число
def encode(s) :
res =
for i in range (len (s)) :
# Добавляет АSСII -значение текущего трехзначного символа к res
res = res +str ("10 :03)".format (ord(s [i])))
return int(res)
1111
9
1О
# Декодирует число в текст
11 def decode (х) :
12
tmp =str (x)
13
# Добавляет в начале 1 или 2 нуля в зависимости от значениях
14
if len (tmp) %
3 == 1:
11
15
tmp = 0011 +tmp
16
if len (tmp) %
3 == 2:
17
tmp = "O"+tmp
18
res =
for i in range (len (tmp) //3) :
19
20
# Извлекает символы группами по 3
21
t = tmp [ З*i] + tmp[З*i+l] + tmp[3*i+2]
22
# Добавляется к результату после преобразования в целое , затем в ASCII, затем в символ
23
res = res + str (chr (int (t)))
24
return res
1111
25
26 # Быстрый модульный экспоненциальный алгоритм
27 def rapide_exp(x,n,p) : # Calcul de х,п тоd р
28
if n==l :
29
return х%р
8. Электронное голосование * *
else:
30
31
if n%2 == О :
32
return rapide _ехр ( (х*х) %р, n//2, р)
else:
return x*rapide_exp( (x*x) %p,n//2,p)%p
33
34
35
36
# Алгоритм шифрования RSA с = тле тоd п
37 def encrypt (е , n,m) :
38
return rapide _ехр (m, е , n)
39
4О
41
# Открытый ключ
(е , n) =(15213133, 881856821380357)
42
print ( "Koд для ЗA : " , encrypt(e , n , encode( "OUI")))
43
print ( "Koд для ПPOTИB : " , encr ypt(e , n , encode( "NON")))
44 print ("Код для ВОЗДЕРЖАЛСЯ : " , encrypt (е , n,encode ("BLANC") ) )
При этом знать закрытый ключ необходимости нет*. Чтобы избежать
этой проблемы, следовало бы использовать шифрование RSA-OAEP (Optimal
Asymmetric Encryption Padding), применяемое в стандартах связи . Это шиф ­
рование является вероятностным и основано на использовании быстрой экс­
поненты для вычисления RSA. Следует отметить, что использование быст­
рой экспоненты для вычисления RSA опасно, так как подвергает код атаке по
скрытому каналу с анализом времени выполнения (см. головоломку 6). Эта
проблема также упоминается в головоломке 18 из книги «25 занимательных
головоломок для введения в криптографию»**. Одним из решений, позволя­
ющих избежать этого, является написание кода шифрования RSA, который
занимает одинаковое количество времени нез ависимо от ветвей программы,
что сводится к вычислению классической модулярной экспоненты.
~~ Достигнутые цели
Основными целями данной головоломки можно считать:
•
•
~--
программирование шифрования RSA;
программирование экспоненты (быстрой или нет);
* Д ля расшифро в ки с ообщен и я исполь зуется з акрытый к люч (1 52 13133,
881856821380357).
** Pascal Lafourcade, Malika More, 25 enigmes ludiques pour s'initier а la cryptographie,
Dunod, 2021. https:/ /www.dunod.com/sciences-techniques/25-enigmes-ludiques-pour-initiercryptographie.
4. Решения
•
демонстрацию того, что использование детерминированного шиф­
ра (такого, как RSA) для протокола голосования не обеспечивает
никакой конфиденциальности.
(
Эдвард Сноуден (1983 r. р.)
Эдвард Сноуден был сотрудником ЦРУ* и АНБ**.
В 2013 году, 6 июня, в Гонконге он дал интервью Гленну
Гринвальду и Лоре Пойтрас, которое стало основой для
оскароносного документального фильма «Citizenfour.
Правда Сноудена». В нем он раскрыл журналистам
секретные сведения о таких американских програм­
мах массовой слежки, как PRISM и XKeyscore, а также
Рис.27. Эдвард
Сноуден
о программах шпионажа за серверами.
Эта информация в течение нескольких месяцев публиковалась в много­
численных СМИ по всему миру. Благодаря ей многие люди осознали реаль­
ность и масштабы компьютерной слежки. В результате Сноуден стал одним
из самых известных разоблачителей. Он отправился в ссылку в Москву,
а 22 октября 2020 года Россия предоставила Сноудену вид на жительство.
(
Reddit и Аарон Шварц (1986-2013)
Аарон Шварц -
американский компьютерщик,
отстаивавший свободу информационных техноло­
гий. В 12 лет он создал The Info Network энциклопедию,
заполняемую
пользователями
тернета (как и «Википедия», созданная
2001 года).
онлайн
ин­
15 января
Рис. 28. Аарон Шварц
В 14 лет он принял участие в разработке формата RSS (Really Simple
Syndication), который позволяет в реальном времени получать уведом­
ления об обновлении сайтов. В 15 лет участвовал в разработке лицензий
Creative Commons. В 19 лет он присоединился к команде Reddit - амери­
канского новостного сайта, который считается одним из самых посещае­
мых в мире.
* Центральное разведывательное управление (англ. CIA, Central Intelligence Agency).
** Агентство национальной безопасности (англ. NSA, National Security Agency).
8. Электронное голосование
**
Покинул компанию по идеологическим соображениям после ее погло­
щения компанией Conde Nast. Вместе с Джоном Грубером разработал язык
Markdown, позволяющий легко генерировать НТМL-страницы (Hyper Text
Markup Language). В 2008 году принял участие в проекте TOR (The Onion
Router). Также выступал за открытый доступ к научным публикациям.
@ тоR
Целью проекта TOR стало обеспечение анонимности в интернете для за­
щиты индивидуальных свобод и уважения частной жизни. Сеть TOR предла­
гает способ анонимного посещения веб-сайтов. Принцип работы заключает­
ся в «луковой маршрутизации». Для этого используются методы шифрования
с открытым ключом и совокупность узлов. Для доступа к сайту S с помощью
TOR сначала случайным образом выбирается набор из не менее чем трех сер­
веров TOR, например, А, В и С, открытые ключи которых pkA, pkB и pkC из­
вестны. Затем запрос R к сайту S шифруется для С, затем для В и, наконец,
для А. Такая последовательность шифрования напоминает слои лука. Зашиф­
рованный запрос передается А, который, используя свой закрытый ключ, мо­
жет расшифровать сообщение перед передачей его В. Затем В, используя свой
закрытый ключ, расшифровывает полученное сообщение перед передачей
его С. Наконец, С, в свою очередь, расшифровывает сообщение, чтобы обра­
титься к сайту S с запросом в открытом виде. Если сетью TOR пользуется толь­
ко один человек, то легко выяснить, кто и какой запрос отправил на тот или
иной сайт. С другой стороны, если сетью пользуется много людей, то узнать,
кто с кем общается, уже невозможно. Коммуникации оказываются зашиф­
рованными. Узлы TOR получают зашифрованные сообщения и отправляют
зашифрованные сообщения обратно, что делает пользователей анонимны­
ми, позволяя им слиться с массой пользователей. Девиз TOR -
Privacy loves
company ( «Массовость - друг конфиденциальности»). В октябре 2002 года
была развернута сеть TOR, состоящая из десятка узлов. К 2021 году сеть TOR*
насчитывала уже более 6000 серверов по всему миру.
Рис. 29. Логотип TOR
*
https://www.torproject.org.
9
;#о Биткоин
**
Водонепроницаемый бумажник специально для наличных денег.
Пьер Дак, «До мозга костей»
(
Андрэ Исаак, более известный как Пьер Дак (1893-1975)
Пьер Дак
-
французский юморист
и комик, основавший
юмористическую
13 мая 1938 года
газету «До мозга
кос­
тей». Эпиграф для головоломки взят из
раздела «Объявления». Выпуск этой анти­
гитлеровской газеты прекратился 7 июня
1940 года после выхода 109 номеров. Она
возродилась в период с 1964 по 1966 год,
а затем продолжила выпуск в 1970-е годы.
Рис. 30. Пьер Дак
Дак создал знаменитый дуэт с Франсисом Бланшем. Они вели популярные
радиосериалы «Горе бородатым», «С воровским приветом» и «Всем прекрас­
ных поцелуев». Он также стал создателем шмильблика -
объекта, «строго
целостного, который абсолютно бесполезен и, следовательно, может слу­
жить чему угодно». В 1969 году Ги Люкс и Жак Антуан использовали назва­
ние этого объекта для игрового шоу в прямом эфире, в котором участники
должны были угадать, что такое шмильблик, только по ответам ведущих на
простые вопросы. В основу концепции положен радиоспектакль «Вещь»,
поставленный Пьером Бельмаром. Кроме того, игра «Шмильблик» была
спародирована Колюшем в скетче, успех которого сделал ее еще более из­
вестной. Этот термин теперь стал частью повседневного обихода и, в част­
ности, используется в выражении «Это не приближает нас к шмильблику».
В 1975 году Пьер Дак также стал создателем биглотрона и восхитительного
рецепта варенья из лапши.
9. Биткоин
**
Чтобы произвести майнинг со сложностью 2250 , необходимо найти такое
значение п, при котором
Н(Н(хутрп)) будет меньше 2250 •
Единственный способ решениия -
проверка различных значений п и вы­
полнение вычислений до тех пор, пока не будет найдено подходящее п. Чем
ниже сложность, тем дольше решается задача, поскольку существует мень­
ше чисел, удовлетворяющих неравенству. В Bitcoin сложность периодически
корректируется таким образом, чтобы среднее время решения хеш-задачи
составляло 1О минут для подтверждения транзакций в блокчейне Bitcoin за
этот промежуток времени. На 5 июля 2022 года сложность Вitcoin составляла
29 570 168 636 358.
,1,,
-j- Майнинr биткоина
Программа 14 определяет функцию hashash, которая принимает в каче­
стве параметра сообщение mи дважды применяет функцию SНА-256. Затем
она инициализирует значение транзакции, которое представлено строкой
АВ542 . Наконец, она последовательно проверяет все целые числа, чтобы най­
ти подходящее значение для п, в данном случае п = 50.
Программа 14. Биткоин
1
2
# рiрЗ install pycrypto
from Crypto.Hash import SHA256
3
4
5
def hashash (m) :
h = SHA256 .new ()
6
h. update (m. encode (' UTF- 8' ) )
7
8
9
trnp = h. hexdigest ()
h = SHA256.new ()
h.update (tmp .encode( ' UTF-8 ' ))
1О
return h . hexdigest ()
11
12
13
s= ' AB542 ';
14
15
# Построение первого сообщения при п=О
# Инициализация транзакций А , В , 5 и 42
4. Решения
16 n = О ;
17 z = int (hashash(s+str (n )), 16 )
18
# Пока не найдется подходящее п , ув еличиваем п и заново вычисляем z
while (z>2**250) :
19
20
21
22
23
24
25
n = n+ 1;
z = int (hashash(s+str( n)), 16) ;
рrint ( " Возможный номер транзакции от Алисы к Бобу " \
+ " при предше ствующем блоке 42 ", n) ;
Эта головоломка иллюстрирует принцип работы proof-of-work*, который
лежит в основе создания биткоина и подтверждения транзакций.
я1в Биткоин и принцип ero функционирования
Биткоин был создан Сатоши Накамото в 2009 году. Это первая дематери­
ализованная, распределенная и децентрализованная валюта, и ее появление
стало настоящей революцией, основанной на технологии блокчейн. Сущест­
вующая банковская система основана на доверии к банкам, однако банкир мо­
жет списать деньги вкладчика так, что никто не сможет этого увидеть. И эту
потерю не назовешь несущественной. Чтобы избежать этого, нужна система,
в которой транзакции отслеживаются и не подлежат изменению, что и пред­
лагает биткоин. С другой стороны, у банка нет друзей, а централизация ин­
формации позволяет избежать такой серьезной проблемы, как двойные расхо­
ды, поскольку цифровую монету легко продублировать (см. следующий блок).
Биткоин представляет собой смену парадигмы, которая позволяет отказаться
от централизованной системы управления. Вместо этого майнеры обновляют
бухгалтерскую книгу, подтверждают транзакции и создают биткоины.
В биткоине бухгалтерская книга, обновляемая в режиме реального вре­
мени, является общей для всех пользователей . Список транзакций, кото ­
рые должны быть внесены в книгу, также обновляется в реальном времени
и распространяется среди всех майнеров, которые подтверждают транзак­
ции. Биткоин ввел несколько механизмов для управления этой книгой.
*
С ан.гл. «доказательство выполнен ия работы » -
прин цип защиты сетевых систем
от злоупотр ебления, когда польз ователю нужн о проделать достаточно сложные действия
для получения доступа к серверу, тем самым делая бессмыслен ными массовые обращения
вроде DоS -атак или рассылки спама. - Прим. ред.
9. Биткоин
**
Прежде всего, необходимо обеспечить связь всех новых транзакций
с предыдущими, как в головоломке, с помощью механизма последователь­
ного хеширования блоков транзакций (блокчейна). Таким образом, измене­
ние одной строки в бухгалтерской книге, состоящей из блокчейна, означает
изменение всех строк (т. е. всех блоков), добавленных впоследствии, что
достаточно сложно.
Такой механизм предотвращает мошенничество и делает бухгалтер­
скую книгу защищенной от взлома.
Для подтверждения транзакций майнер* должен выполнить два дей­
ствия.
1.
Проверить, что транзакции действительны. Это означает, что нуж­
но вернуться в блокчейн и найти информацию, необходимую для
проверки того, что счета людей, осуществляющих транзакцию, су­
ществуют и содержат достаточное количество биткоинов.
2.
Решить хеш-задачу, связанную с выбранными транзакциями. Для
транзакции, проведенной в дату d, на сумму т, со счетах на счет у,
с предыдущим блоком р, ставится задача найти такое число п, что­
бы результат следующего вычисления начинался с определенного
количества нулей: SHA256 (SHA256(d, х, у, р, п)), где SHA-256 -
крип­
тографическая хеш-функция. Необходимое количество нулей кор­
ректируется каждые 2016 блоков, т. е. примерно раз в 14 дней, так
что среднее время, затрачиваемое на добычу блока, всегда составля­
ет 10 минут.
Предотвращение двойных расходов
/
Естественно, возникает вопрос: что произойдет, если два майнера одно­
временно решат разные хеш-задачи? Согласно протоколу Bitcoin, это при­
водит к возникновению вилки (иначе говоря, разветвления или развилки),
как показано на приведенной ниже схеме, где каждый квадрат представля­
ет собой блок, связанный с предыдущими в блокчейне, и где есть две вилки,
представленные серыми квадратами.
*
Название «май неры », которое получили компьютерные системы, подтвержда ­
ющие транзакции, отсылает к старателям, искавшим золото во времена Дикого Запада.
С незапамятных времен за ними закрепилась дурная репутация, поскольку они действо­
вали во вред окружающей среде.
4. Решения
Развилки могут привести к двойным тратам, поэтому их необходимо
избегать. Для этого в Вitcoin реализован следующий механизм: при возник­
новении развилки действительной считается только самая длинная ветвь,
а остальные отбрасываются, что аннулирует все транзакции, совершенные
в этих ветвях. По общепринятым оценкам, для окончательного подтверж­
дения транзакции в Bitcoin требуется шесть блоков (около часа), поскольку
модификация последующих блоков становится слишком дорогостоящей.
Бnокчейн
Настоящая революция в биткоине- это изобретение блокчейна. Меха­
низм блокчейна, лежащий в основе Bitcoin, необходим для того, чтобы из­
бежать двойных трат в этой валюте. Блокчейн -
это неизменяемое, непере­
даваемое, распределенное, проверяемое и верифицируемое пространство для
хранения информации. Эти характеристики используются для транзакций
Вitcoin, но могут применяться и в приложениях, требующих отслеживания
операций, например, в блокчейне, разработанном в 2018 году компанией
IBM для распределения продуктов питания (IBM Food Trust). Более подроб­
но о блокчейнах и о том, как работает Bitcoin, читатели могут узнать из книг
Жан-Гийома Дюма и Паскаля Лафуркада «Тринадцать проблем кибербезо­
пасности»* и «О блокчейнах в 50 вопросах»**.
~@ Достигнутые цепи
Цели этой биткоин-rоловоломки -
понять, как работает биткоин, ма­
нипулировать строками и использовать библиотеку для хеширования со­
общений.
* Jean-Guillaume Dumas, Pascal Lafourcade, Treize defis de la cybersecurite : relectures
croisees, La securite de Bitcoin et des Blockchains, CNRS, 2019.
** Jean-Guillaume Dumas, Pascal Lafourcade, Ariane Tichit, Sebastien Varette, Les
Ыockchains en 50 questions, comprendre le fonctionnement et les enjeux de cette technologie
innovante, Dunod, 2018.
10
/о Сиракузы
**
Математика пока не готова к решению таких задач.
Пал Эрдёш о сиракузской гипотез е, цитата по статье Джеффри
Лагариаса «Задача Зх + 1 и ее обобщения»*, 1985 год
(
Пап Эрдёш (1913-1996)
Пал Эрдёш -
венгерский математик, известный
своими многочисленными публикациями: 15 250 ста­
тей, опубликованных совместно с 511 различными со­
авторами! Он работал, в частности, в области теории
графов, теории чисел и комбинаторики. Всего в 21 год
он опубликовал новое доказательство теоремы Че­
бышева, что позволило ему получить докторскую
степень в обход стандартной университетской процедуры.
Рис. 31. Пал Эрдёш
В среде математиков его прозвали « принцем решения задач и абсо­
лютным монархом в постановке задач» за необыкновенную способность
в простом, на первый взгляд, высказывании отразить глубокую суть ос­
новных математических вопросов, которые его интересовали. К постав­
ленным им задачам он часто назначал приз (от нескольких долларов до
нескольких тысяч), отражающий, по его мнению, глубину и сложность
вопроса.
Нигде не имея постоянного жилья, он провел большую часть своей
жизни как кочевник, приезжая на несколько месяцев в разные университе­
ты мира для сотрудничества с многочисленными коллегами, имея при себе
лишь чемодан с записями и результатами исследований.
* Jeffrey С. Lagarias, The 3х + 1 proЫem and its generalizations, American M athematical
Monthly, 92(1): 3-23, 1985.
4. Решения
@число Эрдёwа
В фольклоре математического сообщества число Эрдёша представляет
собой «расстояние сотрудничества» от исследователя до Пала Эрдёша.
Так, по определению, для самого Пала Эрдёша число Эрдёша равно О,
а для исследователей, которым посчастливилось быть его соавторами, оно
равно 1. Затем исследователи, которые публиковались вместе с этими ис­
следователями, имеют число Эрдёша, равное 2, и т. д. Существует более
11 ООО человек с числом Эрдёша, равным 2. У людей, не имеющих публика­
ций, связанных с Эрдёшем, число Эрдёша бесконечно. Например, у Малики
Мор число Эрдёша равно 3, поскольку она публиковалась вместе с Иоган­
ном Андреасом Маковским, который публиковался вместе с Сахароном Ше­
лахом, соавтором Эрдёша. Аналогично, у Паскаля Лафуркада число Эрдёша
равно 3, так как он публиковался вместе с Себастьяном Тикселем, который
публиковался вместе с Нога Алоном, также соавтором Эрдёша. На сайте
Mathscinet* можно легко вычислить число Эрдёша для любого человека.
Решение этой головоломки дает возможность применить важную кон­
цепцию программирования
-
рекурсию . Кроме того, деление, связанное
с определением сиракузской последовательности, подчеркивает важные раз­
личия между типами чисел int и float в Python 3.
Решение головоломки заключается в том, что наименьшим числом, время
полета которого больше 100, является 27, время полета которого равно 111.
'1,,
-'f- Рекурсивное решение
Сиракузские последовательности определяются рекуррентно, поэтому
естественно запрограммировать вычисление рекурсивно, следуя математи­
ческому определению членов последовательности.
Так, для рекурсивного вычисления члена последовательности ранга п
достаточно заметить, что:
•
случай остановки вычисления возникает, когда достигается число
п вычисляемых членов, и тогда необходимо вернуть текущий член
последовательности и;
•
в общем случае, если и четное, то и необходимо разделить на 2 и из
числа п вычисляемых членов нужно вычесть 1, но, если и нечетное,
его следует заменить на 3и+ 1 и также из числа п вычисляемых чле ­
нов необходимо вычесть 1.
* https:// mathscinet.ams.org/mathscinet/freeTools.html ?version=2.
1О. Сиракузы
**
Функция syracuse (u, n) в программе 15 написана с использованием это­
го подхода.
Программа 15. Вычисление членов сиракузской последовательности
## Вычислить рекурсивно член ранга п сиракузской последовательности с первым членом и
def syracuse (u, n) :
if n == О :
return u
if (u %2) == О :
return syracuse(u//2 ,n-l)
else:
return syracuse(З*u+l , n- 1)
1
2
3
4
5
6
7
8
9
1О
# # Вычислить член ранга 15 последовательности с первым членом 7
11 print ( "Члeн последовательности ранга "+str (l5)+" равен "+str (syracuse(7,15) ))
Для деления на 2 важно использовать арифметический оператор / /, ко­
торый позволяет работать с числами типа int, а не оператор / , результатом
работы которого является число типа floa t.
Последний при больших числах дает ошибочный результат. Напри­
u0 = 2361235441021745907775 правильное значение u3 равно
10625559484597856584990, но при использовании оператора / для деления
мер, при
получается значение 1,7709265807663094е+21, то есть совсем другое число
с плавающей запятой.
Возвращаясь к головоломке, отметим , что интерес представляют не зна­
чения членов последовательности, а время полета начального значения
-
другими словами, ранг, на котором впервые достигается значение 1.
Для написания функции temps, выполняющей это вычисление, можно
использовать тот же рекурсивный подход, что и для вычисления членов
последовательности :
•
вычисление останавливается при достижении значения 1, и необхо­
димо вернуть количество шагов в вычислении;
•
в общем случае, если и четное, то и нужно разделить на 2 и приба­
вить 1 к числу шагов вычисления, если же и нечетное, то его нужно
заменить на 3и+ 1 и прибавить 1 к числу шагов вычисления.
С использованием этого подхода написана функция
flight (u, rank )
в программе 17 на странице 148. Сначала задается начальное значение u
и rank, равный О.
4. Решения
Внимание: учитывая, что время полета целого числа не всегда может
быть конечным, нет гарантии, что эта функция рано или поздно остановит­
ся для любого значения u.
Программа 16. Вычисление наименьшего целого числа с временем полета
не менее 100
1
2
3
4
5
# # Вычисление времени полета и путем модификации вычисления членов последовательности
6
## нет никакой гарантии, что эта функция остановится
## Для расчета как значения, так и ранга
## необходимо возвращать не значение , а ранг
## и остановиться, когда полученное значение будет равно 1
##Внимание: поскольку не доказано , что время полета целого числа всегда конечное ,
7
8
9
10
11
12
13
14
# # Функция выполняется с и=инициальное значение и rank=0
def flight(u, rank):
if u == 1:
return rank
if (u%
2) == О :
return flight(u//2 , rank+l)
else:
return flight(З*u+l , rank+l)
15
16
17
18
# # # # Расчет времени полета 7
##print ("Время полета числа 7 равно "+str(flight (7,0)))
19
2О
21
# # Ответ на головоломку :
22
23
i =1
# # вычисление наименьшего целого числа, время полета которого больше 100
t =О
24 while t<lOl :
25
i=i+l
26
t=flight(i,0)
27 print ("Bpeмя полета числа "+str (i)+" равно "+str (t))
~.,,
~
"- r. Рекурсия
Рекурсия -
необычный на первый взгляд способ программирования.
Рекурсивная функция -
это функция, код которой обращается к самой
функции.
в
1О. Сиракузы * *
Стандартным примером рекурсивной программы является вычисление
факториала целого числа п, обозначаемого п!. Эта величина, часто встреча­
ющаяся в комбинаторике, представляет собой произведение целых чисел
ОТ 1 ДО n.
Другими словами, 1! = 1, 2! = 2 х 1 = 2, 3! = 3 х 2 х 1 = 6, 4! = 4 х 3 х 2 х
х 1 = 24, 5! = 5 х 4 х 3 х 2 х 1 = 120 и т. д.
Условно также предполагается, что О!= 1. Тогда определение факториала можно свести к следующим двум правилам:
•
•
п!
= п х (п - 1)!
О!= 1
Следуя этим двум правилам, вычисление 5! включает следующие шаги:
5! = 5 х 4! = 5 х 4 х 3! = 5 х 4 х 3 х 2 х 1! = 5 х 4 х 3 х 2 х 1 х О! = 5 х 4 х 3 х
х 2 х 1 х 1 = 120.
Таким образом, вычисление 5! обращается к другому факториалу,
а именно к 4!, вычисление которого, в свою очередь, обращается к 3!, и т. д.
Так повторяется до тех пор, пока не будет достигнут предельный случай
(О! =
1). Приведенная ниже рекурсивная функция fact (n) реализует этот
способ вычисления факториала.
1
2
3
4
5
def fact (n) :
if n==O:
return 1
else:
return n*fact (n-1)
1.-; \
,_ , Конечная рекурсия
С практической точки зрения функция fact (n) имеет один недостаток:
необходимо запомнить все значения п, п -
1, ... , прежде чем умножение
будет окончательно выполнено при достижении предельного случая. При
больших значениях п это может привести к перегрузке памяти компьюте­
ра. Это распространенная критика рекурсивного программирования. Что ­
бы уменьшить эту проблему, можно написать вариант функции fact (n) ,
в которой одновременно нужно хранить только два числа, а результаты
умножений сохраняются по мере их выполнения во вспомогательной пе­
ременной. Такой тип рекурсии, экономящий память, называется конечной
рекурсией, которая реализована, например, приведенной ниже функцией
fact rt(n) .
4. Решения
1
2
3
4
5
6
7
8
def fact rt (n, res ):
if n==O:
return res
else:
return fact rt(n-1 , n*res)
def facto (n) :
return fact rt(n , 1)
Лямбда-исчисление
Так называемая парадигма функционального про­
граммирования основана на работах Алонзо Черча,
чья модель вычислений известна под названием лямб­
да- исчисление, или А-исчисление. В 1927 году он пред­
ложил интересную статью, в которой рассматривалась
логика при ложной аксиоме выбора. В своем подходе
он считает, что все математические объекты могут
быть определены через функции.
Рис. 32. Алонзо Черч
Он определил целые числа исключительно в виде функций: ноль пред­
ставлен функцией тождества
(функцией, превращающей любой объект
в самого себя), единица - однократным применением функции, двойка последовательным применением той же функции дважды и т. д. В этой же
парадигме он определил сложение и умножение, а также булевы значения
«истина» и «ложь » и логические операторы для построения рассуждений.
Таким образом, он разработал целую теорию, позволяющую описать лю­
бой математический объект в виде функции. Точно так же любое вычисле­
ние (а значит, и любую программу) можно рассматривать как применение
функций. Например, вычисление факториала -
это просто вызов функции
fac t (n ), определенной в приведенной выше программе, которая вызывает
только вычислительные операции (закодированные функциями) и саму се­
бя. Понятие цикла, повсеместно присутствующее в парадигме императив­
ного программирования, заменяется понятием рекурсивного выз ова функ­
ции. Эта теоретическая работа легла в основу парадигмы функционального
программирования. Такие языки программирования, как Haskel, OCaml,
Lisp и Scheme, являются функциональными языками программирования,
основанными на л-вычислениях.
1О. Сиракузы
/
**
Автоматическое доказательство
В
парадигме
функционального
программирования
соответствие
Карри-Ховарда обеспечивает эквивалентность доказательства и про­
граммы. Например, описанная выше программа для факториала fact (n)
является точным переводом его математического определения (О! = 1
и п! = (п -
1)! х п). Поэтому доказательство корректности программы
в
соответствует
точности
рекуррентному
доказательству
корректности
определения. Этот фундаментальный результат информатики лежит в ос­
нове автоматической демонстрации. В этой области программа Coq*, раз­
работанная в INRIA**, служит помощником, который может быть исполь­
зован для получения автоматических доказательств. Например, Жорж
Гонтье и Бенджамин Вернер с помощью Coq смогли повторно обосновать
знаменитую теорему о четырех цветах, утверждающую, что для раскраски
любой политической карты мира достаточно четырех цветов. Coq также
использовался для повторного доказательства теоремы Фейта- Томпсона,
а также для решения многих других задач***.
/
Большие целые числа в Python 3
В современных компьютерах целые числа обычно представляются
в 64 битах. Таким образом, наибольшее представимое целое число равно
264 - 1. В начале XXI в. компьютеры использовали для представления целых
чисел только 32 бита, что ограничивало их размер до 232 - 1.
Однако в таких программах, как Python 3, имеется специальный
механизм, позволяющий работать с произвольно большими целы­
ми числами. Например, при вычислении 2**100 в Python 3 получается
12676506002282294014967032053 76. В языках программирования, не име­
ющих такой возможности, в которых числа int представлены в 64 битах,
невозможно представить 2 100 как целое число: либо возникает «ошибка
переполнения», либо число преобразуется в число типа float, записан­
ное в системе счисления, как на калькуляторе - с потерей точности на
младших разрядах.
* https://coq.inria.fr.
** Institut national de recherche en informatique et en automatique (Национальный инс­
титут исследований в области информатики и управления).
*** https:// madiot.fr/ coq100.
4. Решения
Например,
если
записать
1267650600228229401496703205376,О,
то
це­
лое число
1267650600228229401496703205376 преобразуется в число с пла­
вающей запятой и ведет себя именно так. Таким образом, при оценке 1 +
+ 1267650600228229401496703205376,О == 1267650600228229401496703205376,О по­
лучаем True, в то время как при оценке 1 + 1267650600228229401496703205376==
== 1267650600228229401496703205376 получаем False.
~ Представление вещественных чисел в проrраммировании
Корректно представить число с десятичной запятой на компьютере
достаточно сложно. Большинство вещественных чисел, таких как тт или
✓2, имеют бесконечное число знаков после запятой. С другой стороны,
компьютерное представление числа может иметь только конечное число
разрядов . Это различие между вещественными числами и числами типа
float необходимо понимать для разработки корректных программ вычис­
лений.
Стандарт IEEE 754 определяет числа с плавающей запятой. Это числа,
записанные в научной нотации по основанию 2 в следующем виде: ±s х 2е,
где первый символ -
знак числа, который может быть положительным или
отрицательным; символ s -
положительное число, такое, что 1 ::; s < 2, по­
этому оно записывается как 1, ... ; экспонента е -
относительное целое чис­
ло. Эти элементы хранятся в 64 битах следующим образом:
•
•
1 - битовое поле для знака;
52-битное поле для дробной части s, называемой мантиссой, т. е.
только цифры после десятичной запятой;
•
11-битовое поле для экспоненты.
Это поле используется для представления некоторых вещественных чи­
сел. К сожалению, многие простые вещественные числа, такие как 0,3, не
являются представимыми, то есть не имеют точного представления в дан­
ном стандарте IEEE 754, независимо от архитектуры используемой маши­
ны. Другими словами, число с плавающей запятой, записанное как О . 3, не
равно реальным 0,3, а является лишь приближением.
Путаница между понятиями
float и real является причиной мно­
гих ошибок в программировании. Например, при оценке выражения
О .1 + О . 2 == О. 3 в Python 3, как и в любом другом языке программирова­
ния, получается False. Это связано с тем, что при сложении приближений
0,1 и 0,2 полученное значение не равно приближению 0,3.
в
1О. Сиракузы
**
Отсюда вытекает одно из правил хорошего программирования, кото­
рое чаще всего повторяют преподаватели информатики:
Не пишите тесты на равенство для чисел с плавающей запятой!
Чтобы преодолеть это ограничение для чисел с плавающей запятой,
в языке Python 3 есть функция isclose () в библиотеке math: оценка выраже­
ния math . i sclose (О .1+О . 2, О . 3) , которая выдает True при условии, что в начале
программы была загружена библиотека math с помощью строки import math .
Нет повода надеяться, что в будущем будет изобретено точное компью­
терное представление вещественных чисел или появятся более мощные
компьютеры, которые устранят трудности, связанные с числами типа float.
Фундаментальные теоретические соображения, связанные с работами не­
мецкого математика Георга Кантора конца XIX в., показывают, что это не­
возможно: с одной стороны, в силу природы вещественных чисел, а с дру­
гой -
компьютерных представлений.
f Георr Кантор (1845-1918)
Георг Кантор -
немецкий математик, работы кото­
рого в конце XIX в. произвели революцию в понимании
бесконечности в математике. В частности, он показал,
что не все бесконечности одинаковы и что некоторые из
них больше других! Кантор ввел «трансфинитные» чис­
ла, которые больше любого целого числа. Он показал, что
с ними можно производить вычисления и сравнивать их.
Чтобы понять это, нужно начать с натуральных чисел О, 1,
Рис. 3 3_ Георг
2, 3 и т. д. и представить себе, что все они перечислены.
Кантор
Когда это будет сделано (через бесконечное количество времени ... ), сле­
дующим «числом» окажется первый трансфинитный ординал. Кантор на­
звал его w (греческая «омега»). Далее можно продолжить вычисления и по­
лучить ординалы w + l, w + 2, w + 3 и т. д.
Наконец,
спустя
бесконечное
количество
времени,
появляется
w + w = 2w. Эта головокружительная конструкция продолжается далеко за
пределы воображения и приводит к появлению еще более странных мате­
матических объектов, например так называемых «больших кардиналов» ,
изучением которых в ХХ в. занимались специалисты по теории множеств .
4. Решения
Для сравнения количества элементов в двух бесконечных множествах
Кантор предложил использовать понятие биекции, иначе говоря, соответ­
ствия между членами множеств. Дети, еще не умея пользоваться числами,
могут сравнивать два множества объектов, соотнося каждый элемент од­
ного множества с элементом другого: если в конце не остается ни одного
изолированного объекта, значит, в каждом из множеств было одинаковое
количество объектов, и такое соотношение называется биекцией. На бес­
конечных
множествах
можно
продемонстрировать
некоторые
парадок­
сальные результаты, например, что существует столько же четных целых
чисел, сколько и целых. Чтобы продемонстрировать этот результат, доста­
точно определить биекцию между множеством целых чисел и множеством
четных целых чисел. Для этого с каждым целым числом связывается его
удвоенная величина (или с каждым четным целым -
его половина): О~ О,
1 ~ 2, 2 ~ 4, 3 ~ 6 и т. д.
Множества, которые можно поставить в биекцию с множеством нату­
ральных целых чисел, называются «счетными», так как их элементы можно
перечислить: первый элемент, второй, третий и т. д. Многие бесконечные
множества являются счетными, например, множество ординалов, меньших
2w, или еще менее экзотические множества, такие как множество Q рацио­
нальных чисел. Поэтому естественно задать вопрос, является ли множество
действительных чисел также счетным. Ответ -
нет, и Кантор дал очень эле­
гантное доказательство этого, основанное на аргументе, называемом «диаго­
налью Кантора». Он продемонстрировал, что интервал вещественных чисел
[О; 1[ содержит больше чисел, чем множество N всех натуральных чисел.
Может показаться, что все это очень далеко от информатики, но нет.
На самом деле, компьютерные представления чисел, построенные по осно­
ванию 2, по своей сути являются счетными. Следствием приведенного вы­
ше результата является то, что в компьютере невозможно получить верное
представление вещественных чисел.
~~~
1'- r. Диаrональ Кантора
Чтобы доказать, что интервал вещественных чисел [О; 1[ содержит боль­
ше чисел, чем множество N натуральных чисел, необходимо предположить,
что интервал [О; 1[ является счетным. Это означает, что можно перечислить
его элементы, обозначаемые r1, r2 , r3 и т. д. (числа перечислены не в порядке
возрастания, но это неважно).
1О. Сиракузы
**
Каждое из этих вещественных чисел записывается О, .. .. Если после за­
пятой идет конечное число цифр, то, без потери общности, за последней
цифрой должно следовать бесконечное количество О. Таким образом, чис­
ло 0,3 превращается в 0,30000... Теперь мы можем найти число r Е [ О; 1[
следующим образом: для первой цифры после запятой в r выбрать цифру,
отличную от цифры, расположенной там же в r 1; для второй цифры после
запятой в r выбрать цифру, отличную от цифры в r2; для третьей цифры
после запятой в r выбрать цифру, отличную от цифры в r , и так далее до
3
бесконечности. Если все числа в интервале [О; 1 [ перечислены, то число r
должно быть где-то в этом перечислении. Однако это не так, поскольку по
условию r отличается хотя бы одной своей цифрой от каждого из чисел,
входящих в это перечисление. Это означает, что интервал [О; 1 [ не является
счетным: в интервале [О; 1[ больше вещественных чисел, чем целых чисел
в множестве N. Эта демонстрация может быть адаптирована к любому ин­
тервалу вещественных чисел, каким бы малым он ни был.
~@ Достигнутые цели
Помимо введения понятия рекурсии, эта головоломка также дает воз­
можность рассмотреть вопрос о завершении алгоритмов. Сиракузская гипо­
теза пока остается только гипотезой, поскольку никто еще не смог подтвер­
дить, что функция flight (u,
rank) обязательно завершается во всех случаях.
Теоретически для определенных значений и она может выполняться беско­
нечно долго, порождая все большие и большие значения. Это не является
основной целью головоломки, но в подобном случае хорошо бы ограничить
вычисления. Например, приведенная ниже функция flytime (u, rank) являет­
ся вариантом функции flight (u,
rank) , предложенной в решении. Она оста­
навливается самое позднее при достижении членом ранга 101, даже если это
не окончательное время полета.
1
2
3
4
5
6
7
def flytime(u , rang) :
if u == 1 or rank>l00 :
return u, rang
if (u%2) == О :
return flytime(u//2 , rank+l)
else:
return flytime(З*u+l , rank+l)
4. Решения
Немного изменив основную программу, эту функцию можно использо­
вать и для нахождения ответа на головоломку:
1
2
3
4
5
(i , t) =(l , 0)
while t<lOl :
i = i +l
s, t = flytime(i , 0)
print ("Bpeмя полета числа
"+str ( i )+" равно минимум "+str (t ))
1
~@ Итеративная версия
В языках программирования, относящихся к императивной парадигме,
таких как Python 3, использование рекурсии никогда не является обяза­
тельным. Это означает, что любая рекурсивная функция может быть «де­
рекурсирована», то есть можно написать эквивалентную нерекурсивную
функцию (корректный термин -
«итеративная»), используя цикл. В каче­
стве примера приведем итеративную версию решения головоломки.
Программа 17. Итеративное вычисление последовательности Сиракузы
и наименьшего целого числа, время полета которого не превышает 100
1
# # Итеративная версия
2
3
4
5
6
7
8
9
def syriter (u , n) :
for i in range (l , n+l) :
if u%2==0 :
u=u//2
else:
u=З*u+l
return u
10
11 print (syriter(7 , 16))
12
13 def flightiter (u) :
14
t = О
15
16
17
while u>l :
if u%2==0 :
u = u//2
1О. Сиракузы
18
19
20
**
else:
u = 3*u+l
t = t+l
return t
21
22
23 print (flightiter(7))
24
25
26
i = 1
t = О
27 while t<l0l :
28
i=i+l
29
t = flightiter (i)
30 print ( " Bpeмя полета числа "+str(i)+" составляет "+str(t))
В целях повышения эффективности компиляторы иногда просто авто­
матически дерекурсируют функции, которые были написаны программис­
том как рекурсивные.
11
~о Кривые Безье
**
Формула может быть очень простой и при этом создавать вселенную бес­
конечной сложности.
Бенуа Мандельброт, интервью Эрролу Моррису, 201 О год
Для построения квадратичных кривых Безье, контрольные точки кото­
рых заданы, достаточно воспользоваться программой на языке Python 3. Ис­
пользуемый алгоритм геометрического построения называется алгоритмом
де Кастельжо. Но чтобы понять, как алгоритм работает, есть смысл запастись
терпением и попробовать изобразить кривые карандашом на бумаге и только
потом приступить к программированию. Такое занятие по программирова­
нию без компьютера -
хороший опыт, который наглядно показывает, как
важно представлять себе каждый шаг алгоритма.
'1,,
-j- Алrоритм де Кастельжо
Программа 1, приведенная в тексте головоломки, легко модифицирует­
ся для записи функции segment (xl , yl , х2 , у2) , которая заставляет черепашку
рисовать отрезок по заданным четырем числам, представляющим собой
координаты двух точек.
Далее необходимо определить координаты средней точки отрезка.
В этом заключается роль функции midpoint (xl, yl , х2 , у2 ). После того как эти
два инструмента созданы, наиболее элегантным способом программирова­
ния графика станет использование рекурсивной функции.
В дополнение к шести числам, представляющим координаты контроль ­
ных точек, необходимо ввести параметр п, представляющий глубину, вы­
бранную для расчета.
11 . Кривые Безье
**
Используем утверждения:
•
остановочный случай имеет место, когда п равно О, и заключается
в построении двух отрезков, образующих ломаную линию, которая
соединяет три контрольные точки А, В и С;
•
для общего случая нужно вычислить координаты трех точек D, Е
и F и сделать два рекурсивных вызова, уменьшая глубину на 1: пер­
вый -
с координатами точек А, D и F, а второй -
с координатами
точек F, Е и С.
Функция bezier (xl, yl , х2, у2 , х3 , у3 , n) рекурсивно реализует эту стратегию.
Программа 18. Кривая Безье
1
from turtle import *
2
3
4
5
6
7
8
9
def segment(xl , yl , x2 , y2) :
up ()
goto(xl , yl)
down ()
goto(x2 , y2)
up ()
10 def midpoint (xl , yl ,x2, y2) :
11
return (xl+ х2)/2 ., (yl+y2)/2.
12
13 def bezier(xl , yl , x2 , y2 , x3 , y3 , n) :
14
if n == О :
15
segment(xl , yl ,x2 , y2 )
16
segment(x2 , y2 ,x3, y3)
17
else
18
х4 , у4 = midpoint(xl , yl , x2 , y2)
1
х5 , у5 = midpoint(x2 , y2 , x3 , y3)
20
х6 , у6 = midpoint(x4 , y4 , x5 , y5)
21
bezier(xl , yl , x4 , y4 , x6, y6 , n- 1)
22
bezier(x6, y6 , x5 , y5 , x3, y3 , n-1)
23
24 bezier (40 , 80 , 0, 10, 60 , 30 , 3)
25 bezier (30 , 0, 40 , 30 , 50 , 60 , 3)
26 bezier(70 , 60 , 100, 80 , 80 , 40 , 3)
27 bezier(80 , 40 , 70, 20 , 100 , 30 , 3)
28
29 mainloop ()
4. Решения
Как показано на рисунке ниже, построенном с глубиной 3, решением за­
гадки будет число 42 (ответ на вопрос жизни, Вселенной и всего остального*).
Пьер Безье (1910-1999)
(
Пьер Безье
-
французский инженер-механик
и электротехник, работавший в компании Renault.
В 1962 году он изобрел кривые, впоследствии назван­
ные в его честь, а позднее -
поверхности Безье для
построения кривых и гладких поверхностей для циф­
рового моделирования кузовов автомобилей. Егора­
боты были использованы в начале 1980-х годов компа­
нией Adobe для разработки кривых и шрифтов в языке
Рис. 34. Пьер Безье
описания страниц PostScript, который был практически универсальным ком­
пьютерным форматом, пока его постепенно не вытеснил формат PDF.
Поль де Фаже де Кастельжо (1930 r. р.)
(
Алгоритм построения кривых Безье (точнее, кри­
вых, представляющих собой полиномы Бернштейна),
представленный в этой головоломке, был изобретен
в 1958 году Полем де Фаже де Кастельжо -
француз­
ским математиком, работавшим в компании Citroёn.
Вклад Поля де Кастельжо менее известен, чем вклад
Пьера Безье, поскольку на его работу было наложено
условие конфиденциальности и он получил разреше­
Рис. 35. Поль
ние на ее публикацию только в 1985 году.
де Кастельжо
*
са . -
Одна из сюжетных концепций романа «Автостопом по Галактике» Дугласа Адам -
Прим. ред.
**
11. Кривые Безье
(
Бенуа Мандельброт (1924-201 О)
Автор эпиграфа к этой главе -
Бенуа Мандельброт,
многогранный польско-франко-американский матема­
тик. Он наиболее известен тем, что возродил интерес
общества к фракталам, начав с пятистраничной статьи
о длине побережья Великобритании, опубликованной
в 1967 году. В частности, он показал, что эта длина за-
Рис. 36. Бенуа
висит от масштаба, на котором находится наблюдатель,
Мандельброт
и что береговая линия не соответствует ни объекту размерности 1 (кри­
вой), ни объекту размерности 2 (поверхности), а представляет собой нечто
среднее. Говоря техническим языком, она имеет нецелую хаусдорфову раз­
мерность. Именно это и является одной из существенных характеристик
фрактальных объектов.
Впоследствии Бенуа Мандельброт доказал, что эти математические по­
строения могут быть использованы для моделирования объектов, чья слож­
ность ранее ставила в тупик ученых в различных областях. Принципы это­
го нового направления математики были опубликованы в 1975 году в книге,
ставшей бестселлером: «Фрактальные объекты: форма, случайность и размер­
ность». В книге приведены многочисленные примеры из геологии, гидрологии,
биологии, механики текучих сред, астрономии и других областей. Она также
знакомит читателей с такими математическими конструкциями, как снежин­
ка Коха, треугольник Серпинского и губка Менгера. Все эти объекты облада­
ют свойством быть идентичными, независимо от применяемого к ним увели­
чения, что впоследствии будет названо «самоподобием» (self-similarity) -
еще
одной важнейшей характеристикой фрактальных объектов.
Джеймс Глик в своей книге «Хаос. Создание новой науки», ссылаясь
на работы Бенуа Мандельброта, говорит: «В человеческом сознании фрак­
тал -
это способ увидеть бесконечность».
Множество Мандельброта
В начале ХХ в. Гастон Жюлиа и Пьер Фату определили множество всех
точек с в комплексной плоскости, для которых следующая последователь­
ность комплексных чисел определена рекуррентным методом:
Zo = 0
{ Zn+l = Z~ + С
4. Решения
Это множество названо не в честь ученых, открывших его, а в честь Бе­
нуа Мандельброта, которому 1 марта 1980 года удалось визуализировать его
на экране компьютера. Название придумали исследователи Адриен Дуади
и Джон Хаббард в 1984 году в ходе собственной работы над этим множе­
ством. Множество Мандельброта не является самоподобным в каждой из
своих точек, но оно самоподобно в некоторых точках вдоль своей границы.
Это свойство делает его фрактальным объектом.
о
•
- 1
- 1.5
-1
- 0.5
0.5
~& Достигнутые цели
Эта головоломка дает возможность использовать библиотеку turtle
и написать с ее помощью более сложную рекурсивную программу, чем та,
которая была предложена в решении головоломки 10. Следует отметить,
что использование рекурсии здесь гораздо более фундаментально, чем для
вычисления членов сиракузской последовательности . Ведь для написания
итерационной версии графика кривой Безье необходимо управлять встав­
кой в нужное место новых значений координат концов отрезков, которые
необходимо построить, что совсем не просто. Два рекурсивных обращения
в функции bezier заменяют это сложное управление списком координат на
управление стеком рекурсивных вызовов, который все выполняет самосто­
ятельно. Чтобы еще больше расширить возможности использования биб­
лиотеки turtle, приведем программу для построения снежинки Коха.
Программа 19. Снежинка Коха
1
2
from turtle import *
3
def Line(n, 1) :
# Исходное состояние : перо внизу, направление движения линии влево
4
5
# Финальное состояние : перо внизу, направление движения линии вправо
11 . Кривые Безье
**
if n == 1: forward(L)
else:
Line(n-1 , 1 / 3.0)
left (60)
Line(n-1, 1 / 3.0)
right(120)
Line(n-1, 1 / 3.0)
left (60)
Line(n-1, 1 / 3.0)
6
7
8
9
10
11
12
13
14
15
16 N= int ( input ("Koличecтвo уровней (от 1 до 6): " ))
17 if (type (N) != int) or (N < 1) or (N > 6) :
18
рrint ("Количество уровней не соответствует запросу")
19 else :
20
Length = 550 # Длина линии
21
up ()
22
goto(-300, -180)
23
down ()
24
width(2)
25
left (60)
26
for k in range (3) :
27
Line(N, Length)
28
right(120)
28
up ()
30
goto(O, О)
Эта программа также основана на рекурсивном подходе. Базовый слу­
чай заключается в проведении отрезка заданной длины из исходного по­
ложения черепашки в указанном направлении. В общем случае имеется
4 рекурсивных вызова, получаемых делением длины на 3 и поворотом че­
репашки на необходимый угол (60 или 120 градусов) для получения равно ­
сторонних треугольников.
@ несколько знаменитых фракталов
•
В 1904 году шведский математик Хельге фон Кох придумал снежин­
ку Коха. Это фрактальная кривая, образующая полый невыпук­
лый многоугольник. Исходная фигура образована тремя сторонами
4. Решения
равностороннего треугольника, и алгоритм построения применяет­
ся к каждой стороне треугольника. Чтобы перейти от одного шага
к другому, необходимо:
разделить отрезок на три отрезка равной длины;
построить равносторонний треугольник, основанием которого
является медианный отрезок первого шага и ориентированный
наружу;
удалить основание треугольника из второго шага.
На следующем шаге этот процесс повторяется для четырех новых
полученных сегментов. Теоретически для получения фрактальной
кривой построение должно повторяться бесконечно, так как по
определению это «предельная» кривая, полученная после бесконеч­
ного числа шагов. Существуют варианты снежинки Коха, получен­
ные путем изменения значений углов треугольника или основной
геометрической фигуры, и даже на плоскости (поверхности Коха).
На рисунке показана одна из сторон снежинки Коха.
•
Кривая Гильберта придумана в 1891 году немецким математиком
Давидом Гильбертом. Она представляет собой ломаную линию, по­
лученную из ортогональных отрезков. Базовый шаблон состоит из
трех сторон квадрата. На каждом этапе длина сторон делится на 3.
Каждый «угол» детали предыдущего этапа заменяется новой дета­
лью в той же ориентации, а каждый «торец» также заменяется но­
вой деталью, но повернутой на четверть оборота в сторону, так что
«отверстия» обращены наружу. Остается только по очереди соеди­
нить концы деталей, чтобы получить кривую для следующего шага:
Фрактальная кривая, полученная после бесконечного числа итераций,
обладает свойством проходить через все точки квадрата, построенного из
исходного узора. Еще один фрактал, образованный одной кривой, заполня­
ющей квадрат, -
кривая Пеано, изобретенная Джузеппе Пеано в 1900 году.
11. Кривые Безье
•
**
Существуют фракталы, полученные из двух­
мерных
объектов.
Треугольник
Серпинского
предложен Вацлавом Серпинским в 1915 году.
Он строится из равностороннего треугольника,
разбитого на четыре равносторонних треуголь­
ника одинаковой площади путем рекурсивного
удаления треугольника в центре (который «на­
правлен вниз»), как показано на рисунке.
Губка Менгера
-
это фрактальное твердое тело
в трехмерном пространстве, состоящее из кубов
(см.
рисунок). Оно описано Карлом Менгером в 1926 году.
Аналогично снежинка Мозели, созданная Жанни­
ной Мозели, представляет собой фрактальное твердое
тело, полученное путем построения, аналогичного губ­
ке Менгера, и напоминающее снежинку Коха.
Завершает эту антологию фрактальных объектов
кривая дракона (см. рисунок), придуманная Дж. Э. Хей­
туэем. Эта кривая никогда не пересекает саму себя.
1967 году Мартин Гарднер поместил ее в колонку математических
игр в журнале Scientific American, поскольку ее построение очень просто.
В
На каждом этапе результирующая кривая состоит из отрезков, которые
следуют друг за другом под прямым углом. Первоначально имеется только
один сегмент. Чтобы перейти от одного этапа к другому, следуя по кривой,
необходимо заменить каждый встречный отрезок двумя отрезками, распо­
ложенными под прямым углом и поворачивающимися на 45 градусов по­
очередно вправо и влево.
(
Давид Гильберт (1862-1943)
Этот немецкий математик относится к числу пос­
ледних великих универсальных умов в математике, а его
вклад
охватывает большинство областей
математики
своего времени. Он считается одним из самых выдаю­
щихся математиков ХХ в. и сделал много фундаменталь­
ных открытий в геометрии (аксиоматизация евклидовой
геометрии), функциональном анализе (гильбертовы про­
странства), теории чисел и других областях.
Рис. 37. Давид
Гильберт
4. Решения
На Втором Международном математическом конгрессе в Париже
в
1900 году Гильберт считался одним из лидеров сообщества. В своей
лекции он составил список из двадцати трех нерешенных на тот момент
задач, которые, по его мнению, будут иметь большое значение для мате­
матической дисциплины в будущем. Сегодня двенадцать из них реше­
ны полностью, пять остаются открытыми, остальные решены частично.
Но самое главное -
некоторые из них фактически определили фунда­
ментальное развитие математики в :ХХ в. Опубликовав в 1899 году аксио­
матизацию евклидовой геометрии, Давид Гильберт был убежден, что эта
работа может быть распространена на всю математику, о чем свидетель­
ствует, например, вторая задача в его списке 1900 года. (доказательство
непротиворечивости арифметики). В 1920 году он создал проект, направ­
ленный на достижение этой цели, известный как «Программа Гильберта».
Но в 1930 году знаменитые теоремы Геделя о неполноте, решив отрица­
тельно вторую задачу Гильберта, показали невозможность реализации
этой программы.
Наконец, нельзя не упомянуть о влиянии Гильберта на работы Алана
Тьюринга, одного из основоположников информатики. Статья 1936 года,
в которой Тьюринг определил понятие вычислимости с помощью своих
знаменитых «машин Тьюринга», называется On ComputaЫe Numbers, with
an Application to the EntscheidungsproЫem («О вычислимых числах, с при­
ложением к проблеме разрешимости»). EntscheidungsproЫem (проблема
разрешимости) была поставлена Давидом Гильбертом в 1922 году: ее суть
состоит в том, чтобы найти эффективный метод вычислений (в современ­
ных терминах -
алгоритм) для решения вопроса о том, является ли мате­
матическое утверждение доказуемым или нет. В своей статье он доказы­
вает неразрешимость проблемы остановки, показывая, что не существует
алгоритма, с помощью которого можно было бы в общем случае решить,
закончится ли вычисление или будет продолжаться бесконечно.
~о Во времена древних
12
--------------греков**
- =- -- ----------~-~-----~-~--
Смех -
дело серьезное и нешуточное.
Раймон Девос
Итак, необходимо написать программу, заставляющую зашифрованный
текст подвергаться преобразованиям, соответствующим наматыванию ленты
на цилиндр заданного размера. Поскольку истинный размер цилиндра неиз­
вестен, придется испытывать цилиндры разных диаметров, пока полученный
текст не станет осмысленным .
В примере, приведенном после текста головоломки, мы видим следую­
щий текст:
JENEPERDSJAMAISSOITJEGAGNESOITJAPPRENDS
Он состоит из 39 символов и был зашифрован при помощи цилиндра с дли­
ной окружности в 3 буквы, в результате чего получился следующий шифр:
JISESONSIEOTPIJETARJPDEPSGRJAEAGNMNDAES
Если записать его в три строки, получится расшифровка:
JENEPERDSJAMA
ISSOITJEGAGNE
SOITJAPPRENDS
Подобное разбиение позволяет производить расшифровку вручную, как
поясняется в подсказках. Программа на языке Python 3, выполняющая рас ­
шифровку, основана на вычислительной реконструкции этого разбиения для
заранее заданного размера ключа (т. е. количества строк).
Из приведенной таблицы видно, что первые 13 букв открытого текста на­
ходятся под индексами О, 3, 6
= 2 х 3, 9 = 3 х 3, 12 = 4 х 3 и т. д. шифрованно­
го текста. Последняя полученная этим способом буква -
это А с индексом
36 = 12 х 3. Определенные таким образом буквы - JENEPERDSJAMA.
4. Решения
о
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
J
1
s
Е
s
о
N
s
1
Е
о
т
р
1
J
Е
16
17
18
19
20
21
22
23
24
25
26
27
28
29
т
А
R
J
р
D
Е
р
s
G
R
J
А
Е
30
31
32
33
34
35
36
37
38
А
G
N
м
N
D
А
Е
s
Следующие тринадцать букв -
ISSOITJEGAGNE- имеют соответствен­
но индексы 1 +Ох 3, 1 + 1 х 3 и т. д. вплоть до 1 + 12 х 3. И наконец, послед­
ние тринадцать букв - SOITJAPPRENDS - соответствуют индексам вида
2 + j х 3, где j последовательно принимает все значения от О до 12.
Таким образом, в данном примере дешифрование происходит в три после­
довательных этапа, каждый из которых соответствует восстановлению строки
и состоит из тринадцати шагов, т. е. 39, деленное на 3. В общем случае, когда
цилиндр имеет размер t cy 1, а текст состоит из t ext_ lengt h символов, имеем
tcyl фаз, состоящих из text _l ength//tcyl шагов. Для начала проще предполо­
жить, что деление «сходится», т. е . что: text_ length = tcy1* (text _length/ / tcy1) .
Предыдущие рассуждения показывают наличие двух вложенных цик­
лов for. Внешний цикл соответствует tcyl последовательных фаз, в то время
как внутренний соответствует text _length//tcyl шагам внутри каждой фазы.
Найденные буквы должны быть объединены по ходу работы в строку resul t .
Если деление text _ length/ / tcy1 « не сходится», это означает, что последняя
строка таблицы не заполнена, а также то, что количество символов в полной
строке равно не t ext _length//t cyl , а t ext _length//t baton+ 1. Таким образом, раз­
биение на три строки обычного текста JENEPERDSJAMAISSOITJEGAGNESO
ITJAPPRENDSZ приобретает вид:
JENEPERDSJAМA I
SSOITJEGAGNESO
ITJAPPRENDSZ
Один из способов решения в общем случае - это систематическое выпол­
нение (text _ length/ / tba ton) +1 шагов во внутреннем цикле и обработка только
в том случае, если полученный индекс не превышает text_length- 1, чтобы из­
бежать возникновения ошибки во время выполнения программы.
Программа 20 может быть использована для « намотки ленты » с зашиф­
рованным текстом на цилиндры размером от 2 до 9 (например) методом ски­
талы. Размер цилиндра 1 не представляет особого интереса, так как не дает
12. Во времена древних греков
**
никакого шифрования. Перед запуском программы нельзя быть уверенным
в том, что требуемый цилиндр действительно находится в диапазоне от 2
до 9. Если это не так, то придется проверять цилиндры большего размера.
Программа 20. Наматывание ленты на цилиндры разного размера
1
2
3
4
5
6
7
# # Расшифровка зашифрованного текста методом скиталы
# # Открытие текстового файла для считывания
# # и загрузка содержимого в виде символьной строки
file = open (' .. /Enigmes/Enigme12 .txt', ' r' )
text = file .read()
file .close()
8
9
# # Попытка расшифровки с цилиндрами размером от 2 до 9
1О text_length=len (text)
11 for tcyl in range (2 , 10) :
12
result = ""
13
# # Внешний цикл соответствует разным фазам дешифрования
14
15
16
17
18
19
20
for i in range (tcyl) :
# # Внутренний цикл соответствует различным шагам внутри каждой фазы
for j in range (text_length/ / tcy1+ 1) :
if i+tcyl*j<text_length:
result = result + text[i+tcyl*j]
print (" размер цилиндра "+str (tcyl))
print (result)
'1,,
-<r- Решение rоловоломки
Следующий текст получен при размере цилиндра 5:
А tort ou а raison . On ne
sait jamai s qui а rai son ou qui а t ort . C' est
diffici le de juger . Moi , j ' ai longtemps donne raison а tout le monde . Jusqu ' au
jour о~ je me suis apercu que la plupart des gens а qui je donnais raison
avaient tort ! Donc, j ' avais raison ! Par consequent, j ' avais tort ! Tort de
donner raison а des gens qui avaient l e tort de croire qu ' ils avaient rai son .
C' est-a-dire que moi qui n' avais pas tort , je n' avais aucune raison de ne pas
donner tort а des gens qui pretendaient avoir raison , al ors qu 'i ls avaient
tort ! J ' ai raison , non? Puisqu ' ils avaient tort ! Et sans raison , encore !
4. Решения
La, j 'insiste , parce que ... moi aussi, il arrive que j'aie tort . Mais quand
j 'ai tort, j ' ai mes raisons , que je пе donne pas . Се serait reconnaitre mes
tort s ! ! ! J ' ai raison , non? Remarquez ... il m' arrive aussi de donner raison а
des gens qui ont raison aussi . Mais, la encore , c'est un tort . C' est comme si
je donnais tort а des gens qui ont tort. Il n' y а pas de raison ! En resume ,
je crois qu ' on а toujours tort d' essayer d' avoir raison devant des gens qui
ont toutes les bonnes raisons de croire qu 'ils n' ont pas tort !*
Из скетча Раймона Девоса «Правда или ложь»
Раймон Девос (1922-2006)
(
Раймон
Девос
блестящий
-
франко-бельгийский
юморист, чьи абсурдистские каламбуры, по выражению
Жоэля Мартена в «Библии противоречий», никогда не
бывают пассивными. Девос также выступал в качестве
мима, придумывал комические парадоксы и оригиналь­
ные юморески. Нередко его тексты приходится слушать
или читать несколько раз, чтобы вникнуть в содержание.
Он обладал талантом играть с языком, выдавая полные
юмора фразы.
•
Охранник -
Рис. 38. Раймон
Девос
это единственный человек, кого вы выставляете за
дверь в тот день, когда нанимаете.
•
Если моей жене суждено однажды овдоветь, я бы предпочел, чтобы
это произошло еще при моей жизни.
•
Я верю в свое бессмертие, но боюсь, что умру раньше, чем смогу
в нем убедиться.
*
Правда или ложь. Никогда не знаешь, кто прав, а кто винов ат. Трудно судить.
Долгое время я соглашался со всеми . Но однажды я понял, что большинство людей,
с которыми я соглашался, были неправы! Значит, я был прав! Значит, я был неправ! Не­
правильно соглашаться с людьми, которые ошибались, считая, что они правы. Другими
словами, у меня, который не ошибался, не было причин не соглашаться с людьми, которые
утверждали, что они правы, когда они были неправы! Я прав, не так ли? Потому что они
были неправы! И без всякой причины! Я настаиваю на этом, потому что .. . Я тоже иногда
ошибаюсь. Но когда я н еправ , у меня есть свои причины , которые я не называю. Это было
бы признанием моей неправоты! Я прав, не так ли? Разумеется .. . Я также иногда соглаша­
юсь с людьми, которые тоже правы. Но это, опять же, ошибка. Это как если бы я ошибался
в отношении людей, которые ошибаются. Но ведь для этого нет никаких оснований ! Ко­
роче говоря, я считаю, что всегда неправильно пытаться быть правым перед лицом людей,
у которых есть все основания считать, что они не ошибаются!
12. Во времена древних греков * *
•
Ничего не поделаешь, говорят. Это и значит -
ничего не делать!
Последняя цитата взята из его знаменитого скетча «Говорить, чтобы
ничего не сказать». Посмертная книга «Помечтаем о словах», вышедшая
в 2007 году, содержит мысли, анекдоты и отрывки из ранее не публико­
вавшихся скетчей, собранные Пьером Эрраном, секретарем и менеджером
Раймона Девоса, в период с 1972 по 2006 годы.
~~ Достигнутые цели
В этой головоломке есть две алгоритмические трудности:
•
•
настройка двух вложенных циклов f or;
тонкое арифметическое управление индексами символов в строке
с помощью двух счетчиков цикла.
~@ Разматывание ленты
Для того чтобы решить эту головоломку, начнем с выбора значения
tcyl , а затем возьмем символы в следующем порядке: тот, который нахо­
дится в позиции О , тот, который находится в позиции text_length//tcyl,
затем тот, который находится в позиции 2*text_length//tcyl, и т. д. Как
и в программе 20, тонкость заключается в управлении индексами между
tcyl * (text_length/ / t cyl) и text_length-1.
Программа 21. Шифрование текста методом скиталы
1
2
# # Шифрование текста методом скиталы
3
4
# # Открытие файла с текстом для считывания
# # и загрузка содержимого в виде символьной строки
5
6
7
fi le = open (' Complement12 .txt ', 'r' )
text = file .read()
text = text .replace( ' \n ' , ' ' )
fi le.close()
8
9
10 text_length=len( text)
11 tcyl=int (input ( " Введите размер цилиндра \n") )
12 result = ""
13 for i in range (text length//tcyl+l ) :
4. Решения
14
for j in ranqe (tcyl) :
15
if i +j* (text_length//tcyl)<text length :
16
result = resul t + text[ i +j*(text_l ength//tcyl ) ]
17 print (result)
Таким образом, текст Раймонда Девоса становится расшифровкой тек­
ста из головоломки.
В программе 20, как и в программе 21, управление памятью неопти­
мально. Поскольку символьные строки в Python являются неизменяемыми
объектами, повторное выполнение присваивания
result=result+text [ . . . ]
приводит к тому, что каждый раз создается новая строка, в которую запи­
сывается новое значение. Чтобы избежать этого, можно модифицировать
программу так, чтобы она работала с изменяемым объектом, например со
списком.
Для этого перед операторами цикла прописывается инициализация
переменной:
result=[] , которая затем обновляется внутри циклов так:
result.append(text[i+j*(text_length//tcyl) ]) .
Наконец, после циклов список может быть преобразован в символь­
ную строку для более наглядного отображения с помощью команды:
result= ' ' . j oin (result ).
13
~о Четверичное
дерево**
---------------- =- -
Квадратики были логичным решением. Конечно, это решение представ­
лялось не единственно возможным, но мы использовали квадратики. Это
оказалось большой глупостью, от которой с тех пор страдают все.
Рассел Кирш, интервью Рэйчелу Эренбергу
для издания WIRED, 28 июня 2000 года
(
Рассел Кирш (1929-2020)
Рассел Кирш был инженером в NIST. Он изобрел сканер изображений
и ввел понятие пикселя -
наименьшего графического элемента на экране.
Существует два метода представления цветов пикселей, заимствованных
из природы. Первый, RGB, является аддитивным, как при наложении света
разных оттенков. Второй, СМУК, является субтрактивным, как при смеши­
вании тюбиков с краской.
Для решения этой головоломки нам необходимо преобразовать четве­
ричное дерево в изображение. Это можно сделать вручную, но программа на
Python 3 явно быстрее и надежнее. Лучше всего подходит формат изображе­
ний Р РМ.
1
Формат изображений
В компьютере или смартфоне экран служит ключевым элементом вза­
имодействия с устройством. Поэтому изображения занимают центральное
место в использовании этих аппаратов, а их качество, размер и способы
манипулирования ими являются важными элементами в отношениях че­
ловека и машины.
4. Решения
Существует множество различных форматов изображений. Пять наи­
более используемых в вычислительной технике -
это ВМР,
TIFF, GIF, JPEG,
или JPG, и PNG.
ВМР (Windows BitMaP): этот формат был использован в вычислитель­
ной технике одним из первых. Он прост, поскольку каждый пиксель пред­
ставлен символом. Изображения не сжимаются, что делает их очень боль­
шими. В настоящее время он практически не используется.
TIFF (Tagged Image File Format): этот формат ориентирован на про­
фессионалов (полиграфистов, рекламщиков и т. д.). Он позволяет получать
изображения очень высокого качества, но при этом имеет очень большой
размер, хотя и меньше, чем у файлов формата ВМР, поскольку файлы TIFF
можно сжимать (сжатие LZW).
GIF (Graphics Interchange Format): этот формат является одним из стан­
дартов интернета. Файлы имеют небольшой размер, поскольку изображения
содержат только 256 цветов. Части изображения могут быть прозрачными.
JPEG (Joint Photographic Expert Group): этот формат предлагает не­
сколько степеней сжатия, которые влияют на качество изображения. Он
стал стандартом для изображений в интернете, поскольку при сжатии
получаются изображения меньшего размера. Это означает, что они могут
быть быстро загружены даже при низкоскоростном соединении.
PNG (PortaЫe Network Graphic): это стандарт для интернета, посколь­
ку позволяет использовать прозрачность, как и формат GIF, поддерживает
16,7 млн цветов, а также позволяет сжимать данные.
Еще существует формат RAW, который не претендует на статус стандарта.
Такие файлы создаются цифровыми зеркальными фотоаппаратами или ска­
нерами. Этот формат характеризуется тем, что он практически полностью
состоит из «необработанной» (англ. raw) информации, снятой камерой.
Форматы изображений можно разделить на две основные категории:
•
Так называемые «растровые изображения» (ВitMap ): фотографии,
рисунки и т. д. Эти цветные или черно-белые изображения состоят
из точек (пикселей). При увеличении или уменьшении таких изоб­
ражений возникают определенные проблемы с определением пик­
селей измененного изображения. С другой стороны, они часто име­
ют высокое качество, поскольку содержат всю информацию.
•
«Векторные изображения» состоят из кривых, которые определяют
формы с помощью уравнений. Даже сложные векторные изображе­
ния требуют меньше места в памяти, чем растровые. Более того, они
легко масштабируемы.
13. Четверичное дерево
,1
**
Форматы растровых изображений
Существуют сжатые и несжатые форматы растровых изображений.
Несжатые форматы изображений, такие как ВМР (Windows BitMaP), Р РМ
(PortaЫe РiхМар file format), PGM (PortaЫe GrayMap file format) и РВМ (PortaЫe
BitMap file format), относятся к несжатым, т. е. все пиксели присутствуют
на изображении. Преимуществом этих форматов можно считать качество
изображений, поскольку без сжатия не происходит потерь. С другой сторо­
ны, эти файлы имеют большой размер. Например, изображение ВМР разме­
ром 800 х 600 пикселей занимает 1,37 Мбайт.
Форматы РРМ, PGM и РВМ просты в описании, но очень велики, поскольку
пиксели в них представлены АSСП-символами, занимающими по 1 байту.
Формат РВМ был определен Джефом Посканцером в 1980-х годах для мо­
нохромных изображений, закодированных в АSСП-тексте. Затем, в 1988 го­
ду, он разработал форматы PGM (для полутоновых изображений) и Р РМ
(для цветных изображений). Эти файлы строятся следующим образом:
•
номер формата: Р 1 лутоновых и РЗ -
•
для черно-белых изображений, Р2 -
для по­
для цветных;
символ пробела, который может быть пробелом, табуляцией или
новой строкой;
•
•
•
•
ширина изображения;
символ пробела;
высота изображения;
для форматов PGMи РРМ -
символ пробела, за которым следует чис­
ло, обозначающее количество используемых цветов;
символ пробела;
Pl
двоичные данные изображения:
символ 1 для черных пикселей и О для
# Изображение буквы J
6 1О
О О О О 1 О
О О О О 1 О
О О О О 1 О
О О О О 1 О
О О О О 1 О
О О О О 1 О
1О О О 1О
О 1 1 1 О О
белых пикселей, как, например, следу­
о о о о о о
•
•
изображение кодируется
построчно, начиная с верх­
ней строки;
каждая
строка
кодируется
слева направо.
Кроме того, все строки, начинаю­
щиеся с #, игнорируются.
РВМ: эти изображения используют
ющее изображение буквы
J.
J
о о о о о о
4. Решения
PGM: эти изображения состоят из символов, представляющих оттен­
ки серого с максимальным значением менее 65536 (кодируются в символах
ASCII). Например, с пятнадцатью возможными уровнями серого цвета, где
черный кодируется О, а белый - максимальным значением 16, можно по­
строить следующее изображение.
□ □Р
Р2
#
Изобразить
слово
LOOP
24 7
15
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
7
7
7
7
о
О
о
о
о
о
о
о
О
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
3
3
3
о
о
7
7
7
7
7
7
о
о
7
7
7
7
о
о
3
3
3
3
3
о
О
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
11 11 11
11
о
о
11
о
о
11
о
о
11 11 11
о
11
11
11
11
11
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
15 15 15 15
15
о
о 15
15 15 15 15
15
о
о
о
15
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
о
РРМ: в этих изображениях пиксели окрашиваются. Для каждого пиксе­
ля необходимо указать три значения, обозначающие пропорции красного,
зеленого и синего цветов. Максимальное значение цвета, меньшее 65536
(кодируется в символах ASCII), фиксируется в изображении. Например,
в следующем коде это значение равно 255, и изображение представляет
прямоугольник из красного (255,О,О), зеленого (О,255,О) и синего (О,0,255)
цветов в первой строке и прямоугольник из желтого (255,255,0), белого
(255,255,255) и черного (О,О,О) цветов во второй строке.
РЗ
#
Три
столбца ,
две
строки
3 2
#
Максимальное
255
255
о
255 255
значение
о
о
■
- 255
о 255
о
255 255 255
о
о
255
о
о
о
Сжатые форматы. Файлы изображений, где представлены все пиксели,
очень велики. Существует несколько механизмов сжатия данных, позволя ­
ющих уменьшить размер файла. Существует два основных типа сжатия: без
потерь и с потерями.
13. Четверичное дерево
**
@векторные изображения
Существует
множество
форматов
векторных
файлов,
таких
как
Postscript, PDF, Adobe Flash, Illustrator или SVG. За стандарт формата век­
торных изображений принят формат PostScript, называемый EPSF (Encapsulated PostScript File) и имеющий расширение .eps или .epsf. Векторные
изображения меньше растровых и масштабируются без искажений. Эти
изображения состоят исключительно из формул, используемых для рисо­
вания составляющих их кривых. Кривые Безье (см. головоломку 11) -
один
из типов кривых, часто используемых в таких изображениях.
'1,,
-<r- Преобразование четверичного дерева в изображение
Изображения представлены матрицами (список списков в Python 3).
Далее необходимо подумать о создании функции
concatenation, которая
объединяла бы 4 изображения в соответствии с порядком расположения
четверичных деревьев -
по сторонам света, т. е. СЗ, СВ, ЮЗ и ЮВ. Эта
функция строит изображение нужного размера, заполненное нулями, ис­
пользуя функцию zeros из библиотеки numpy. При обходе каждого элемента
матрицы создается копия элементов в соответствии с их местом.
Далее для восстановления изображения используется рекурсивная
функция display, принимающая в качестве параметров четверичное дерево
и размер. Если значение четверичного дерева размера t равно О или 1, то
должно быть построено изображение, содержащее соответственно только
О или 1. В противном случае на каждой части текущего четверичного дерева
должны быть собраны 4 изображения, возвращаемые рекурсивными вызо­
вами функции quadtreetoimg.
Затем необходимо поместить построенное изображение в файл в фор­
мате РРМ (как это уже было сделано с изображением в головоломке 5).
Программа 22. Преобразование четверичного дерева в ррm-изображение
1
2
3
4
5
import numpy as np
def concatenation (nw , ne , sw, se, size):
res = np . zeros ([ size, si ze])
for i in range (size) :
4. Решения
6
for j in range (size) :
7
if i<size//2 :
8
if j<size//2:
9
res[i,j] = nw[i,j]
10
else:
11
res[i,j] = ne[i,j-size//2]
12
else:
13
if j<taille//2 :
14
res[i,j] = sw[i-size//2,j]
15
else:
16
res[i,j] = se[i-size//2,j-size//2]
17
return res
18
19 def quadtreetoirng(quadtree,size) :
2О
if quadtree==O:
21
return np . zeros ([size, size])
22
elif quadtree==1:
23
return np .ones([size,size])
24
else:
25
return concatenation(quadtreetoirng(quadtree[O] ,size//2) ,
26
quadtreetoirng(quadtree[l] , size//2),
27
quadtreetoirng(quadtree[2] , size//2) ,
28
quadtreetoirng(quadtree[З] , size//2),size)
29
3О qt = [ [О , О , О , [1, О , О , О] ], \
31
[0 ,0, [0,1,0,0] ,0] ,\
32
[0 ,0,0, [[1 , О , 0 , 1] , [0 ,0,1, 1] ,0,0]] ,\
33
[0 ,0, [[0,0,1,1], [0 ,1,1,0] ,0,0] ,0]]
34
35 lines = 16
36 irng = quadtreetoirng (qt, lines)
37
38 file = open ("solution-quadree .pprn", "w")
39 file .write("Pl \n# Quadree \n")
40 file .write(str (lines)+" "+str (lines)+" \n")
41 for i in range (lines) :
42
for j in range (lines) :
43
file.write(str (int (irng[i , j])))
44
file.write("\n")
45 file. close ()
13. Четверичное дерево
**
На экране появится следующее изображение:
• •
•___,/'
~@ Достигнутые цели
Цели данной головоломки заключаются в формировании следующих
навыков:
•
•
•
•
•
•
---
ознакомиться с форматами цифровых изображений;
научиться работать с изображениями в формате РРМ;
представлять матрицу в виде списка списков;
работать со списками списков;
записывать в файл;
создавать рекурсивную функцию.
14
✓о Семь мостов
Кёни гсберга
Слава -
***
это мостик, по которому можно перейти через пропасть.
Оноре де Бальзак, «Мысли, сюжеты, фрагменты »
(
Оноре де Бальзак (1799-1850)
Известный французский писатель, автор более
90 романов и новелл. Наибольшую известность ему
принесли произведения, собранные под общим заго­
ловком «Человеческая комедия». Он стремился реа­
листично описывать социальные условия своего вре­
мени через героев, как, например, в романах «Отец
Горио » и «Евгения Гранде» . Творчеством Бальзака
вдохновлялись многие авторы, в том числе Эмиль
Золя, Гиде Мопассан и Марсель Пруст.
Рис. 39. Оноре
де Бальзак
В 1736 году Эйлер решил задачу о семи кёниrсберских мостах и сформу­
лировал следующую теорему: связный граф допускает эйлерову цепь тогда
и только тогда, когда все его вершины имеют четную степень. Таким обра­
зом, граф, соответствующий задаче о мостах, не является эйлеровым: невоз­
можно один и только один раз пересечь каждый из мостов города и вернуться
в исходную точку. В любом случае хотя бы один мост придется пропустить.
Чтобы продемонстрировать этот результат, необходимо сначала пока­
з ать, что если связный граф допускает эйлерову цепь, то все его вершины
имеют четную степень. Если эйлерова цепь существует и одна из ее вершин
i, то , выйдя из i, необходимо вернуться в эту вершину по другому ребру,
а значит, у вершины должно быть как минимум два ребра. Таким образом,
в каждую вершину приходят два различных ребра при каждом проходе, что
14. Семь мостов Кёнигсберга
***
демонстрирует четность числа ребер на вершину. Таким образом, все верши­
ны должны иметь четную степень.
Остается показать, что если все вершины имеют четную степень, то связ­
ный граф имеет эйлерову цепь. Демонстрация носит структурный характер
и проводится по алгоритму, который предложил математик Карл Хирхоль­
цер из Баден-Бадена. Начиная с некоторой вершины графа, можно построить
контур, поскольку степени вершин четные, и, следовательно, разбить граф на
несколько контуров. Затем их можно объединить и получить эйлерову цепь.
Существует несколько способов моделирования графа. Для решения этой
головоломки мы решили моделировать граф с помощью словаря в Python 3,
который содержит для каждой вершины список ее соседей. Для моделиро­
вания графа головоломки можно, например, пронумеровать вершины, начи­
ная с О, следующим образом. Приведенный ниже граф можно смоделировать
с помощью следующего словаря:
graph =
[1, 2] 1
о
1 [ О , 2, 4, 5] 1
2 [ О , 1, 3, 41 5, 6] 1
3 [2, 4] 1
4 [1, 2, 3, 5, 6, 8] 1
5 [1, 2, 41 6, 7, 8] 1
6 [2, 41 5, 7] 1
7 [5, 6, 8, 9] 1
8 [41 5, 7, 9] 1
9 [7, 8] 1
}
Этот граф является эйлеровым, и вот цикл, найденный программой:
[0, 1, 4, 6, 2, 5, 6, 7, 8, 9, 7, 5, 8, 4, 2, 3, 4, 5, 1, 2, 0] .
4. Решения
~Словарь
Словари в Python 3 представляют собой неупорядоченные наборы объ­
ектов. Словарь содержит элементы, состоящие из ключа для доступа к нему
и значения. Ключ должен быть уникальным, поэтому дубликаты не допус­
каются. Если для одного и того же ключа введены два значения, то второе
значение записывается поверх первого.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
d = { } # Словарь пуст
d=
3': 1 2+ 1' 1
' 5' : ' 10//2 ',
' 3' :' 6//2 ' # 2 -й ключ для ' 3', который перезаписывает первый
1
print (d) # Отображает { ' 3': '6//2 ', ' 5': ' 10//2' }
d[ ' 5'] = ' 3+2 ' # Меняет значение ключа ' 5'
d [' 6' ] = ' 3*2' # Добавление новой записи
print (d) # Отображает { '3': '6//2 ', '5': '3+2', ' 6' : ,3*2'}
print (d .get( ' 5' )) # Отображает 3+2
print (d[ ' 5' ]) # Отображает 3+2
item = d.pop( ' 6' ) # Удаляет запись ' 6' и возвращает ее значение в item
print (d) # Отображает { ' 3': ' 6//2', ' 5': ' 3+2 ' }
Как и списки, словари в Python 3 являются мутабельными и динамиче­
скими объектами. Словарь может содержать объекты любого типа. Слова­
ри часто используются для создания сложных, модифицируемых структур
данных. Они также хешируются в оперативной памяти, поэтому получить
доступ к ключу быстрее, чем к элементу списка.
'1.,,
-'f- Построение эйлерова пути
В этой головоломке граф представляется словарем вершин и списком
их соседей. Программа 23 содержит функцию has _euler _tour, которая оп­
ределяет, имеет ли граф эйлерову цепь, проверяя, что количество ребер на
вершину четное, обходя их одно за другим.
14. Семь мостов Кёнигсберга
***
Программа 23. Проверка, является ли граф эйлеровым
1
2
3
4
5
6
def has_euler_tour(graph) :
# Проверка того , что все вершины имеют четное число соседей
for connections in graph .values() :
if len (connections)%2 1 = О :
return False
return True
7
8 if has_euler_tour(graph) is False :
9
print (' Данный граф не содержит эйлеровых путей . ' )
10 else:
11
print (' Этот граф является эйлеровым . ' )
Функции программы
24 могут быть использованы для построения
эйлерова пути, если граф является эйлеровым. Согласно алгоритму, пред­
ложенному Карлом Хирхольцером в 1873 году, сначала необходимо знать,
как построить цикл в графе. Затем необходимо построить другой цикл из
одной из вершин первого цикла. Для этого достаточно соединить циклы
между собой, чтобы получился более крупный цикл, и повторять этот про­
цесс до тех пор, пока не останется свободных вершин. Таким образом, по­
строенный цикл будет представлять собой эйлерову цепь. Поскольку граф
является эйлеровым , каждая вершина имеет четное число соседей. Поэтому
можно построить новый цикл из вершины, у которой еще есть соседи, не
входящие в построенный эйлеровский цикл.
Функция first_vertex_connect принимает на вход граф и вершину и на­
ходит соседей данной вершины. Функция vertex_wi th _connections принима­
ет в качестве параметров цепь и граф. Она выдает первую вершину в цепи,
которая еще имеет доступного соседа в графе. В онлайн-решении для обоих
вопросов головоломки приводится один файл на языке Python 3.
Программа 24. Построение эйлерова графа
1
2
3
4
5
6
7
def first_vertex_connect(graph, vertex) :
# Поиск соседней вершины
for s, connections in graph.items() :
if vertex in connections :
return s
return None
4. Решения
8
9
def vertex_with_connections(tour, graph):
# Поиск первой вершины в контуре с доступным соседом
1О
for vertex in tour:
11
if graph.get(vertex, None) is not None and len (graph[vertex]) > О :
12
return vertex
13
return None
14
15 def construct_euler_tour(graph, first vertex):
16
# Инициализация контура в первой вершине
17
18
19
20
tour = [first vertex]
current- vertex = first - vertex
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# Поиск неиспользованных связей
while current vertex is not None :
# Инициализация нового контура в текущей вершине
cycle = [current_vertex]
current_vertex_cycle = cycle [-1] # Последняя вершина контура
# Построение цикла
# Выбор первой вершины в цикле в качестве соседней с текущей вершиной
next_vertex_cycle = first_vertex_connect(graph, current_vertex_cycle)
while next_vertex_cycle is not None:
# Добавляет вершину к циклу
cycle.append(next_vertex_cycle)
# Удаление соединения из графа
graph[current_vertex_cycle] .remove(next_vertex_cycle)
graph[next_vertex_cycle] .remove(current_vertex_cycle)
# Выбор следующей вершины
current_vertex_cycle = next_vertex_cycle
next_vertex_cycle = first_vertex_connect(graph, current_vertex_cycle)
# Добавление построенного цикла к эйлеровой цепи
index = tour.index(current vertex)
tour = tour[:index]tcycle+tour[index+l :]
42
# Выбор следующей вершины
43
current_vertex = vertex_with_connections(tour, graph)
44
return tour
45
46 if has_euler_tour (graph) is False:
47
print (' Этот граф не содержит эйлеровой цепи .' )
48 else:
49
рrint ( ' Эйлерова схема \n', construct euler tour(graph,0))
14. Семь мостов Кёнигсберга
***
[Ш доЭйлера
В своей книге «Математические развлечения», вышед­
I
шей в 1882 году, Эдуард Люка приводит рисунки, которые
предлагается выполнять не отрывая пера от бумаги. Это
соответствует нахождению эйлерова пути в графе. Одну
из задач Люка формулирует так: «Мне рассказывали, что
Рис. 40. Подпись
Магомет начертал свою подпись, состоящую из двух про-
Магомета
тивоположных
полумесяцев,
одним
росчерком
острия
своего
И приложил рисунок. Нарисовать его «одним росчерком» -
ятагана».
это то же са­
мое, что найти эйлерову схему на графе, образованном пересечениями линий на рисунке.
(
Эдуард Люка (1842-1891)
Эдуард Люка -
французский математик, родив­
шийся в Амьене и занимавшийся теорией чисел. Он
изучал числа Фибоначчи, которые обобщил, введя
числа Люка в виде L n+2
= Ln+ 1 + Ln при L0 = 2 и L1 = 1.
Он также изобрел тест на первичность, усовершенствованный Дерриком Лемером в 1927 году и ныне из­
вестный как тест на первичность Люка-Лемера. Бла­
годаря его методике в 1876 году удалось показать, что
170141183460469231731687303715884105727 -
простое
число, которое также называют числом Мерсенна М
127 •
Рис. 41. Эдуард Люка
В своей знаменитой теореме Люка представил биномиальные коэффи­
циенты. Он также изобрел линейку Генайля-Люка, усовершенствованную
по сравнению с палочками Непера или линейкой Непера. Это изобретение
Джона Непера (изобретателя логарифма Непера) в
1617 году позволило
быстрее выполнять умножение и деление, возводить в степень и извлекать
корни с помощью линейки посредством алгоритма. Люка написал четырех­
томную книгу «Математические развлечения», в которой изложил знаме­
нитую задачу о кёниrсберrских мостах. Он также придумал игры «Ханой­
ские башни» и «Пипопипетка».
(
Марен Мерсенн (1588-1648)
Марен Мерсенн -
монах, физик, математик и философ. Он изучал
акустику и предложил законы Мер сенна в своем трактате «Универсальная
гармония», написанном в 1637 году.
4. Решения
Там описана работа струнных инструментов,
таких как фортепиано и арфа. Одновременно с Га­
лилеем изучал падение тел.
В математике известен простыми числами Мер­
2r - 1. Простые числа
Мерсенна встречаются редко: к 2018 году их было
сенна, которые имеют вид
открыто всего пятьдесят одно.
(
Рис. 42. Марен Мерсенн
Леонардо Фибоначчи ( ок. 1170-1250)
Знаменитый итальянский математик, в 1202 году
написал трактат по вычислениям и счету, Liber abaci
( «Книга вычислений»), в котором были введены
арабские числа (в том числе и ноль). В этой работе он
изучал рост популяции кроликов и, в частности, та­
кую задачу: «Некто поместил пару кроликов в опре­
деленное место, огороженное со всех сторон, чтобы
Рис.43. Леонардо
узнать, сколько пар будет произведено от этой пары
Фибоначчи
за год, поскольку в их природе заложено порождать
другую пару через один месяц, а способность рожать
у них появляется на второй месяц после рождения».
Для решения этой задачи он предполагает, что:
•
кролики могут давать потомство только после двух месяцев существования;
•
в начале каждого месяца каждая пара, способная к деторождению,
рождает ровно одну новую пару кроликов;
•
кролики никогда не умирают.
Для моделирования популяции кроликов он ввел знаменитую последо­
вательность Фибоначчи, определяемую F1 = F2 = 1 и Fn+2 = Fn+i + Fn. В 1220 го­
ду он написал еще один трактат по геометрии.
@ ханойская башня
В своей книге Эдуард Люка приписывает изобретение этой игры Н. Кла­
усу де Сиаму, преподавателю колледжа Ли-Су-Стен. В игре есть три баш­
ни: А, В и С. В начале игры в башне А находятся диски, уложенные от самого
большого к самому маленькому (самый большой находится внизу), а баш­
ни в и с пусты.
14. Семь мостов Кёнигсберга
-
Цель игры
***
переместить все
диски в башню С и освободить баш­
ни А и В. Правила игры просты:
•
перемещать только один диск
за раз;
•
никогда не класть больший
диск на меньший.
Рис. 44. Ханойская башня
В своей книге Люка представляет игру с помощью истории о монахах, ко­
торые двигают башню из 64 золотых дисков, и когда они закончат, наступит
конец света. Для решения задачи с 64 дисками требуется не менее 264 - 1 хода,
что составляет около 584,5 млрд лет, если делать один ход в секунду.
Эта игра -
великая алгоритмическая классика, поскольку она решается
естественным образом с помощью очень простого рекурсивного алгорит­
ма. Этот алгоритм состоит в том, чтобы переместить все диски, кроме одно­
го, из башни А в башню В, используя в качестве посредника башню С, затем
переместить оставшийся диск в башню С и, наконец, переместить диски из
башни В в башню С, используя в качестве посредника башню А.
функция Ханой(n , А , В , С)
если
n-/- О
Ханой(n - 1 ,
А,
С , В)
Переместить диск с А на С
Ханой(n - 1 ,
В,
А , С)
@i
U Пипопипетка
Эта игра для двух игроков известна также под
названием «Квадратики» или «Сундучки». Игра про­
водится на листе бумаги в клетку, у каждого игрока
карандаш своего цвета. Игроки по очереди проводят
линию своего цвета по краю клетки. Выигрывает тот
игрок, которому удастся нарисовать наибольшее ко­
А
в
личество квадратов своего цвета. Выше представле ­
на партия между игроком А, играющим сплошными
линиями, и игроком В, играющим пунктирными ли-
ниями. Каждый игрок нарисовал по одному квадрату, поэтому счет у них 1: 1.
- - - - - - - - - - - - - - - - - - - - -~
4. Решения
@& Достигнутые цели
Эта головоломка преследует несколько целей:
•
•
•
•
смоделировать задачу, построив граф;
работать с графами;
построить цикл в графе;
объединить два цикла.
;#о Точный счет***
15
Чрезмерная спешка представляет опасность не только на дороге, но
и в обучении.
Жак Капеловичи, En plein delire scolaire
( «В эпицентре школьного абсурда»), 1984 год
Жак Капеnовичи (1922-2011)
(
Жак Капеловичи, известный также как Мастер Ка­
пело, -
знаменитый грамматист, ведущий и судья игро­
вого шоу «Игры в 20:00» в период с 1976 по 1987 годы,
обладавший невероятной выдержкой. В 1990-х годах он
также принимал участие в игровом шоу «Цифры и бук­
вы». Эта программа, созданная в 1965 году, до 1972 го­
да называлась «Самое длинное слово». В 2022 году эта
ежедневная игровая
программа по- прежнему выходит
в эфир, что делает ее долгожителем французского теле­
Рис. 45. Мастер
видения.
Капело
Суть задачи заключается в том, чтобы решить головоломку, просчитав
множество возможных результатов с помощью абстрактного синтаксиче­
ского дерева. Для этого в Python 3 можно представить узел дерева словарем,
первое поле которого соответствует значению корня дерева, а второе
-
вы­
ражению, используемому для вычисления этого значения. Первый узел дере­
ва состоит из шести листьев, каждый из которых содержит значение одной из
начальных карточек и ее выражение в виде символьной строки.
Далее необходимо вычислить все комбинации из двух карточек, исполь ­
зуя четыре
возможные
операции:
сложение, вычитание,
умножение
и
це­
лочисленное деление. Из оставшихся деревьев затем строятся новые дере­
вья -
до тех пор, пока добавление новых комбинаций станет невозможным.
После того как список всех возможных деревьев построен, остается только
4. Решения
выбрать корень, соответствующий искомому значению или наиболее близ ­
кий к нему. Чтобы не перебирать все деревья заново, в предлагаемом здесь
решении ближайшие или точные искомые значения определяются и сохра­
няются в списках.
Если программист не проявит внимательность и смекалку, построение та­
ких деревьев может очень сильно затянуться и занять много памяти. Не исклю­
чено, что тесты программы заставят ваш компьютер работать на полную мощ­
ность в течение длительного времени. Предлагаемое решение для шести карт
обрабатывается всего несколько секунд на стандартном офисном компьютере,
и мы надеемся, что ваше решение будет столь же эффективным и верным.
'1.,,
-i- Построение графа
В программе 25 функция calculate принимает в качестве параметров
два абстрактных синтаксических дерева и операцию. Если возможно, она
применяет операцию и возвращает созданное таким образом новое абс­
трактное синтаксическое дерево. Новое выражение должно быть постро ­
ено с использованием круглых скобок, чтобы было удобнее читать резуль­
тат. Условия на отрицание означают, что в промежуточных вычислениях
не может быть отрицательных чисел. Условие для умножения: нет необхо­
димости умножать на ноль или на единицу. Наконец, условия для деления:
запрещено делить на ноль, бесполезно делить на единицу, а деление должно
быть целочисленным.
В инициализационной части функции sol ve необходимо создать пер­
вый узел, содержащий все имеющиеся на старте карточки. Должны быть
инициализированы список решений и список приближенных решений.
Затем, пока создаются новые деревья, необходимо проверять комбина­
ции с оставшимися деревьями. Например, при наличии трех листьев а , Ь , с
и оператора результат после инициализации будет [ 1 а 1 , 1 Ь 1 , ' с ' ] . Затем де­
рево обогащается операторами ' [ ( а+Ь ) ', ' с ' ] ,
затем
в
' (а+Ь ) +с ', ] ,
тексте
[' ( а+с ) +Ь ', ] ,
головоломки,
[' (а+с) ', ' Ь ' ] , ' [ (Ь+с) ', ' а ' ] ,
[' ( Ь+с ) +а ', ] . По формуле, приведенной
существует
девять
возможных деревьев,
так
как
9 = (~) + (~)(~) + 3 = 3 + 3 + 3.
Заметим также, что если цель достигнута, то продолжать работу с этим
деревом нет необходимости.
Наконец, нет необходимости дважды просматривать список построен­
ных абстрактных синтаксических деревьев для поиска решений; достаточ­
но сохранять их по мере построения.
15. Точны й счет * * *
Программа 25. Точный счет
1
2
3
4
5
6
7
8
9
1О
import random
# Набор возможных карточек
game = [1, 2, 3, 4, 5, 6, 7,8, 9, 10, 25, 50, 75,100] *2
operations = [' +' , 1 - 1 , ' *' , ' /' ]
# Случайный набор изб карточек
cards = random.sample(game, 6)
# Цель по правилам игры выбирается случайным образом
11 goal = random.randint (l0l, 999)
12
13
рrint ( ' Используйте эти карточки 1 1 cards, 1 1 чтобы получить ' , goal)
14
15 # Функция вычисляет из двух деревьев а 1 и а2 следующее дерево с помощью данной операции
16 def calculate (al , а2 , operation) :
17
if operation == ' +' :
18
return j'value' :al[ ' value' ]+a2[ 'value' ],
19
' expression' :' (' +al [' expression' ]+' +' +а2 [' expression' ]+' )' )
20
if operation == 1 - 1 and al[ 'value' ]>a2['value' ]:
21
return !'value' :al [' value' ] -а2 ['value' ),
22
'expression' :' (' +al[ 'expression' ]+'-' +a2[ 1 expression 1 ]+ 1 ) 1 )
23
if operation == ' *' and al[ 'value' ]>l and a2 ['value'] >l:
24
return !'value' :al [' value' ]*а2 [' value' ],
25
' expression' :' (1 +al[ 1 expression 1 ]+ 1 *1 +a2[ 1 expression 1 ]+ 1 ) 1 )
26
if operation == ' /' and al['value']>l and a2['value' ]>l and al[' value'] %a2[ 'value' ] == О :
27
return !'value' :al ['value' ]//а2 ['value' ),
28
' expression' :' (1 +al[ 1 expression 1 ]+ 1 / 1 +a2[ 1 expression 1 ]+ 1 ) 1 )
29
return None
30
31 def sol ve (cards, goal) :
32
# Инициализация : используйте карточки как листья на дереве
tree = []
33
34
leaves = []
35
for card in cards:
36
leaves. append (!
37
' value': card,
4. Решения
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
'expression' : str(card)
1)
tree .append (leavesl
# Инициализация решений
exact solutions = [1
close_solutions = [(' value' :О, 'expression' :' О ' 11
for card in tree [О 1:
if card [' value' 1 == goal :
exact_solutions.append (card [' expression' 11
if aЬs (card[ ' value' 1-goal) <aЬs (close_solutions[OI ['value' 1-goal) :
close solutions = [cardl
# Конструкция всех возможных решений
index = О
while index < len (tree) :
current cards = tree [index1
for i in range (O, len(current_cards)) :
cardl = current cards [i1
for j in range (О, i) : # Рассмотрите каждую пару карт только один раз
card2 = current_cards [j1
for operation in operations:
result = calculate (cardl, card2, operation)
if resul t is None:
# Если расчет не удался, попробуйте другой путь
result = calculate (card2, cardl, operation)
# В противном случае нет смысла в замене, поскольку а+Ь =Ь+а и а*Ь =Ь*а
if resul t is not None:
if result [' value' 1 == goal :
# Добавлять только в том случае, если решение еще не существует
present = False
for s in exact solutions:
if s == result [' expression' 1:
present = True
break
if present == False:
exact_solutions.append (resul t [' expression' 1)
# Нет необходимости добавлять решение к дереву
else:
15. Точный счет * * *
76
# Построение нового узла с результатом
77
# плюс оставшиеся деревья !разные деревья из i и j )
78
new node =[result]
79
for kin ranqe (~, len (current_cards1) :
if k != i and k != j:
80
81
new_node,append (current_cards [k] 1
82
# Добавление нового узла в дерево
tree .append (new_node)
83
84
# При необходимости обновить приблизительное значение
85
if аЬs (result[ 1value 1 ]-goal) <аЬs (close_solutions [~] [1 value 1 ]-goal) :
86
87
close solutions=[result]
elif aЬs (result[ value ] -goa l ) == \
88
1
1
аЬs (close_solutions [~] [ value ]-goal) :
89
# Добавляет только в том случае, если приближенное решение еще не существует
90
present =False
91
92
for s in close solutions:
if s[1expression 1 ] == result[ 1expression 1 ] :
93
94
present =True
95
break
if present == False:
96
97
close_solutions.append (result)
index =indext1
98
return exact- solutions, close- solutions
99
100
101 exact_sol, close_sol =solve(cards, goal)
102 if len(exact sol)>~:
1О 3
print (1Как минимум одно решение : 11
104
for solution in exact sol:
105
print(solution, 1 =1, goal)
1О 6 else :
1О 7
print (1Точного решения нет : 11
1О 8
for s in close sol:
109
print(s[ 1expression1 ] 1 1 =1 1 s[ 1value 1 ])
1
1
Эта головоломка требует от вас отличного знания языка программирова­
ния и умения придумать итерационный алгоритм, который строит все воз­
можные абстрактные синтаксические деревья. Она входит в перечень задач
4. Решения
книги Programmation efficace, Les 128 algorithmes qu'il faut avoir compris et
codes dans sa vie («Эффективное программирование: 128 алгоритмов, кото­
рые вы должны понять и запрограммировать в течение своей жизни») Крис­
тофа Дюрра и Джилл-Джинн Ви.
~~ Достигнутые результаты
Основные цели данной головоломки:
•
•
смоделировать сложную задачу;
построить абстрактные синтаксические деревья и манипулировать
ими;
•
оптимизировать алгоритм.
~--
'1,,
-j- Головоломка 16
Самые внимательные читатели наверняка увидели, что на обложке книги
спрятана еще одна загадка -
16-я. Посмотрите: какое слово зашифровано?
Отгадка: если сложить буквы в правильном порядке, получится слово
Python. Загадки именно на этом языке вы и решали в этой книге.
Список иллюстраций
О. Гвидо ван Россум
1. Закодированный текст
2. Картонные блины и кулинарная лопатка
3. Сортировщик IBM D3, выпущенный на рынок в 1958 году
4. Шадок
5. Бутылка Клейна
6. Лента Мёбиуса
7. Символ перерабатываемых материалов
8. Логотип Python
9. Текст, зашифрованный методом скиталы
1О. Пример шифрования с помощью скиталы
11. Нельсон Мандела
12. Карта Кёнигсберга
13. Модель семи мостов Кёнигсберга
14. Портрет Леонарда Эйлера кисти Якоба Эмануэля Хандманна (1753)
15. Ричард Столлман
16. Генри Эрнест Дьюдени
17. Иоганн Карл Фридрих Гаусс
18. Бертран Рассел
19. Курт Гедель
20. Тони Хоар
21. Китайские счеты, « Британская энциклопедия » (1875)
22. Клод Пьеплю
23. Геродот
24. Рене Декарт
25. Пол Кочер
26. Уильям Роуэн Гамильтон
27. Эдвард Сноуден
28. Аарон Шварц
29. Логотип TOR
30. Пьер Дак
31 . Пал Эрдёш
32. Алонзо Черч
33. Георг Кантор
34. Пьер Без ье
35. Поль де Кастельжо
36. Бенуа Мандельброт
37. Давид Гильберт
38. Раймон Девос
39. Оноре де Бальзак
40. Подпись Магомета
41 . Эдуард Люка
42. Марен Мерсенн
43. Леонардо Фибоначчи
44. Ханойская башня
45. Мастер Капело
Список аббревиатур
ANSSI
Agence nationale de la securite des systemes d'information
ASCII
American Standard Code for lnformation lnterchange
САО
Conception assistee par ordinateur
CIA
Central lntelligence Agency
СМУК
Cyan, Magenta, Yellow, Кеу
CMJN
Cyan, Magenta, Jaune, Noir
CSP
Communicating Sequential Processes
FSF
Free Software Foundation
GIMP
GNU lmage Manipulation Program
GNU
GNU is Not Unix
GPL
General PuЬlic License
HTML
HyperText Markup Language
IBM
lnternational Business Machines Corporation
INRIA
lnstitut national de recherche en informatique et en automatique
MIT
Massachusetts lnstitute ofТechnology
NIST
National lnstitute of Standards and Technology
NSA
National Security Agency
ОАЕР
Optimal Asymmetric Encryption Padding
OCaml
Objective Categorical Abstract Machine Language
PSFL
Python Software Foundation License
RAM
Random Access Memory
RGB
Red-Green-Blue
RSS
Really Simple Syndication
RSA
Rivest Shamir Adelman
SHA
Secure Hash Algorithm
TOR
The Onion Router
TSP
Travel Salesman ProЫem
Алфавитный указатель
А
IoT, 96
Algol 60, 99
ANSSI, 41
ASCII, 65, 75, 78, 81
Audacity, 77
AZERTY, раскладка, 82
к
в
ВЕРО, раскладка, 82
Big Data, 96
Blender, 77
Keccak, 44
L
LibreOffice, 77
Lisp, 142
LOGO, 50
м
с
Markdown, 131
МIТ, 50
Citroёn, 152
N
СМУК, 30, 165
Colemak, раскладка, 82
Coq, 143
CSP, 100
F
Firefox, 77
Free Software, 76
FSF, 77
G
GIMP, 77
GNU, 76
GPL, 77
NIST, 41
NP, 125
о
ОАЕР, 129
OCaml, 80, 142
р
PIN, 33,117
Postscript, 169
PROLOG, 88
Proof-of-work, 134
PSFL, 78
н
Q
Handbrake, 77
Haskel, 142
HTML, 131
Quicksort, 99
QWERTY, раскладка, 82
IВМ , 26, 136
Inkscape, 77
INRIA, 143
Interstice, 101
R
Reddit, 130
Renault, 152
RGB, 29,165
RSA,39,40,41,58, 117, 127- 129
RSS, 130
Алфавитный указатель
s
в
Scheme, 142
Вернер, Бенджамин, 143
SНА,43
Ви, Джилл-Джинн, 186
Strand Magazine, 83
Википедия,97, 130
Вилка, 135
т
TOR, 131
г
Галилей, 178
u
Гамильтон, Уильям Роуэн, 125
Unicode, 78
Unix, 77
UTF-8, 78
Гарднер, Мартин, 157
Гатри, Фрнэсис, 3 7
Гаусс, Иоганн Карл Фридрих, 87
Гедель, Курт, 89
V
Геродот, 109
VLC Media Player, 77
Гильберт,Давид, 156
А
Гистией, 110
Абстрактное синтаксическое дерево, 60
Авторское лево, 77
Авторское право, 77
Адлеман, Леонард М., 100
Алгоритм
Глик, Джеймс, 153
Голдвассер, Шафи, 100
Гонтье, Жорж, 143
Гринвальд, Гленн, 130
Гудфеллоу, Джеймс, 33
Евклида, 41
д
жадный, 104, 122
Дак, Пьер, 132
Шора, 42
Двойные расходы, 134
Алиса, 43, 127
Двоичная система, 105
Алон, Нога, 138
Дворак, Август, 82
Амьен, 177
Девос, Раймон, 159
АНБ , 130
Декарт, Рене, 113
Андрэ, Исаак, 132
Деление Евклидово, 67
Апартеид, 53
Демарат, 109
Аристагор, 11 О
Десятичное представление, 70
Арифметика модулярная, 40
Дили, Уильям, 82
Атака по скрытым каналам, 71, 117
Дон Кихот, 91
Б
Бальзак, Оноре де, 172
Безье, Пьер, 47, 150, 152
Белл, Тим, 50
Бельмар, Пьер, 132
Дуади, Адриен, 154
Дьюдени, Генри Эрнест, 83
Дюрра, Кристоф, 186
ж
Жезл Плутарха, 52
Бенгио, Йошуа, 100
Жюлиа, Гастон, 153
Биби - бинарная система, 106
3
Биглотрон, 132
Бит, 105
Биткоин, 43, 133
Знак, 144
Золя, Эмиль, 172
Бланш, Франсис, 132
к
Боб,43
Калининград, 56
Бутылка Клейна, 28
Кантор, Георг, 145
Алфавитный указатель
Капеловичи,Жак, 181
Ми кали, Сильвио, 100
Карп,Ричард, 100
Милнер, Рабин, 100
Карри-Ховард, 143
Мински, Марвин, 100
Квантовый компьютер, 42
Мозели, Жаннина, 157
Кейли, Артур, 37
Мопассан, Ги де, 172
Кёнигсберг, 56, 172
Морган, Август де, 37
Кирш, Рассел, 165
Мутабельные объекты, 96
Кларк, Эдмунд, 100
Клейн, Феликс, 28
Клерк, Фредерик де, 53
Кнут, Дональд, 100
Коллатц, Лотар, 46
Колюш, 132
Кочер, Пол, 117
Коулман, Шай, 82
Криптарифм, 23
н
Накамото, Сатоши, 43, 134
Непер, Джон, 177
Неполнота, 90
о
Орден искусств и литературы, 108
Основание 10, 66, 70, 96
Отпечаток, 44
Криптовалюта, 43
Ксеркс, 109
п
Кук,Стивен,100, 125
Паланик, Чак, 117
Кутюрье, Жан Поль, 27
Палочка Непера, 177
л
Ландау, Эдмунд Георг Герман, 98
Память оперативная, 174
Парадокс лжеца, 91
Пеана, Джузеппе, 156
Лапуант,Боби, 106
Пейперт, Сеймур, 50
Лекун, Янн, 100
Пиксель, 29, 165
Лемер,Деррик,177
Пипопипетка, 177, 179
Лента Мёбиуса, 28
Плиний Старший, 110
Лесли, Лэмпорт, 100
Побочный эффект, 95
Лессиг, Лоренс, 76
Пойтрас, Лора, 130
Линейка Непера, 177
Показатель Эйлера, 40
Листинг, Иоганн Бенедикт, 28
Полиморфизм типов, 80
Логика Хоара, 99
Полином Бернштейна, 47,152
Люка, Эдуард, 177
Посканцер, Джеф, 167
Лямбда-исчисление, 142
Премия
Нобелевская, 53, 89, 100
м
Маковски, Иоганн Андреас, 138
Мандела, Нельсон, 52
Мандельброт,Бенуа, 153
Мантисса, 144
Мартен,Жоэль, 162
Мастер Капело, 181
Тьюринга, 100
Проблема разрешимости, 158
Программа Гильберта, 158
Пруст, Марсель, 172
Пьеплю, Клод, 108
р
Мёбиус, Август Фердинанд, 28
Рассел, Бертран Артур Уильям, 89
Менгер, Карл, 157
Рекурсия, 140
Мерсенн, Марен, 177
Метод исключения Гаусса, 89
конечная, 141
Ривест, Рональд Л. , 100
Алфа в итны й ука затель
Россум, Гвидо ван, 18
Ферма, Пьер де, 41
Руксель,Жак,27, 102
Фёрзег, Уолли , 50
Фибоначчи, Леонардо, 178
с
Функциональное программирование, 142
САП,47
Сахарон, Шелах, 138
х
Свободное программное обеспечение, 76
Хаббард, Джон, 154
Сервантес, Мигель де, 91
Хандманн, Якоб Эмануэль, 58
Серпинский,Вацлав,157
Ханойские башни, 177
Сифакис, Джозеф, 100
Хватал,Вацлав, 125
Скиталы метод, 160
Хейтуэй, Дж. Э., 157
Сложность, 87, 92, 98, 101
Хеш-задача, 43, 135
Смежный граф, 124
Хеш-функция, 43, 135
Сноуден, Эдвард, 127, 130
Хеширование, 43
Сортировка
Хинтон, Джеффри, 100
вставкой,97
Хирхольцер,Карл, 173, 175
по максимуму, 97
Хоар, Чарльз Энтони Ричард, 93, 99
по минимуму, 97
Холлерит, Герман, 26
пузырьковая, 98
Хэмминг, Ричард, 100
слиянием, 97
ц
шейкерная, 98
Сортировщик IВМ D3, 26
ЦРУ, 130
Стандарт IEEE 754, 144
ч
Стеганография, 109
Черепашка, 49
Столлман, Ричард, 75
Чернила
Счеты, 106
невидимые, 11О
т
симпатические, 11 О
Теорема
Черч, Алоиза, 142
о четырех цветах, 143
ш
Фейта-Томпсона, 143
Шадоки,27, 102
Ферма (малая), 41
Шамир, Ади, 100
Чебышева, 137
Шварц, Аарон, 130
Тиксель, Себастьян, 138
Шестнадцатеричная система, 105
Тип, 79
Шестнадцатеричный формат, 30, 105
типизация
Шифрование асимметричное, 42
динамическая, 80
Шмильблик, 132
сильная, 79
Шор, П итер, 42
статическая,80
Тьюринг Алан, 158
у
э
Эйлер, Леонард, 40, 56, 58, 172
Эйнштейн, Альберт, 27
У айтхед, Альфред Норт, 89
Экспонента, 129, 144
Устойчивость к конфликтам, 44
Эмерсон, Аллен, 100
ф
Эрдёш, Пал, 137
Фаже де, де Кастельжо Поль, 150, 152
я
Фату, Пьер, 153
Яо, Эндрю, 100
ISBN 978-5-04-192646-5
1111111111 1
9 785041 926465 >