В отличие от естественных языков, которые используются для общения людей, языки программирования используются для передачи команд человека компьютеру. Каждый язык программирования включает в себя словарь команд и правила составления программы. Чтобы компьютер «понял», что от него хотят, человек должен придумать четкий алгоритм действий, а потом записать его с помощью имеющихся команд в соответствии с правилами языка программирования. Полученный текст — программа — передается компьютеру; после этого текст анализируется, обрабатывается, и компьютер выполняет команды человека. Пример простейшего языка программирования — калькулятор: к примеру, если мы хотим вычислить сумму чисел 123 и 456, мы вводим в него «программу» (выражение) 123 + 456, после чего она анализируется компьютером, выполняется, и калькулятор возвращает число 579.
Существует большое количество языков программирования, широко использующихся на практике: C++, C#, Python, R и многие другие. Отметим, что многие команды в каждом из этих языков представляют собой обычные слова английского языка (например, if, while, for). Иногда языки программирования, однако, придумывают не для промышленного использования, а для развлечения. Одним из таких языков программирования является язык Shakespeare ‘Шекспир’. По словам разработчиков этого языка, цель его создания — сделать так, чтобы текст программы был красивым и воссоздавал дух произведений Шекспира. Как следствие, программа на языке Shakespeare оформляется как пьеса, а команды этого языка являются репликами персонажей Шекспира.
Ниже приведена программа на языке Shakespeare и перевод ее текста на русский язык.
Программа |
Перевод |
Romeo and Juliet: arithmetic of love. Romeo, Son to Montague. Juliet, Daughter to Capulet. Tybalt, Nephew to Lady Capulet. Friar Laurence, a Franciscan. Act I: Differences between Montagues and Capulets. Scene I: Romeo and Juliet’s conversation. Juliet: You are as noble as a rich Lord! Open your heart! Romeo: You are as beautiful as the sum of a lovely small blossoming white rose and the sum of a tiny gentle yellow flower and death! Open your heart! [Exit Juliet] Scene II: Romeo and Tybalt’s altercation. Romeo: You big purple cowardly pig! Open your heart! Tybalt: You are as miserable as the sum of a little fatherless coward and a leech! Open your heart! [Exeunt] Act II: Sum of Montagues and Capulets. Scene I: The wedding. Juliet: You are as charming as the sum of myself and the sum of an amazing old King and a trustworthy hero! Open your heart! [Exit Juliet] [Enter Friar Laurence] Romeo: You are as good as the sum of a large rich mighty kingdom and Hell! Open your heart! Friar Laurence: You the sum of thyself and a cursed handsome ___A___! Open your heart! [Exit Friar Laurence] Scene II: The happy ending. Romeo: ______________B______________. [Exeunt] |
Ромео и Джульетта: арифметика любви. Ромео, сын Монтекки. Джульетта, дочь Капулетти. Тибальт, племянник жены Капулетти. Брат Лоренцо, монах-францисканец. Акт I: Различия между Монтекки и Капулетти. Сцена I: Разговор Ромео и Джульетты. Джульетта: Ты благороден, как богатый Господин! Излей свою душу! Ромео: Ты прекрасна, как сумма чудесной маленькой цветущей белой розы и суммы крошечного нежного жёлтого цветка и смерти! Излей свою душу! [Джульетта уходит] Сцена II: Перебранка Ромео и Тибальта. Ромео: Ты, большая фиолетовая трусливая свинья! Излей свою душу! Тибальт: Ты ничтожен, как сумма маленького труса, не имеющего отца, и пиявки! Излей свою душу! [Уходят] Акт II: Сумма Монтекки и Капулетти. Сцена I: Свадьба. Джульетта: Ты очарователен, как сумма меня и суммы восхитительного старого Короля и героя, заслуживающего доверия! Излей свою душу! [Джульетта уходит] [Входит брат Лоренцо] Ромео: Ты хорош, как сумма большого богатого могущественного королевства и ада! Излей свою душу! Брат Лоренцо: Ты, сумма себя и проклятого привлекательного ___! Излей свою душу! [Брат Лоренцо уходит] Сцена II: Счастливый конец. Ромео: ___________________________. [Уходят] |
В результате работы программы компьютер поочередно вывел следующие 8 чисел:
2 23 -8 -5 29 __C__ 25 48 |
Задание 1. Заполните пропуск C, написав вместо него число, которое выведет программа в процессе своей работы.
Задание 2. Каким из слов можно заполнить пропуск A: angel ‘ангел’ или devil ‘дьявол’?
Задание 3. Заполните пропуск B предложением на языке Shakespeare, которое состоит не более чем из 10 слов.
Задание 4. Почему, если убрать из сцены I акта II строчку [Exit Juliet] ‘Джульетта уходит’, компьютер выдаст сообщение об ошибке и не будет корректно выполнять программу?
Примечание 1. Знание как английского языка, так и программирования для решения задачи не требуется.
Примечание 2. Названия пьесы, актов и сцен, а также описания персонажей играют декоративную роль в программе и не влияют на ход ее работы.
Когда один герой говорит другому фразу, начинающуюся со слова «ты», он передает ему некоторое число, зашифрованное далее в предложении; после слов «Излей свою душу!» это число выводится на экран. Вопрос: как шифруются числа?
Когда в тексте программы встречается словосочетание the sum of ... and ... ‘сумма ... и ...’, оно обозначает настоящую сумму чисел, зашифрованных словосочетаниями, стоящими на месте многоточий. Когда в программе встречается выражение вида the sum of X and the sum of Y and Z ‘сумма X-а и суммы Y-а и Z-а’, по смыслу оно означает сумму X-а, Y-а и Z-а (по правилам языка Shakespeare, нельзя просто написать the sum of X, Y, and Z ‘сумма X-а, Y-а и Z-а’).
Прилагательное, находящееся на месте многоточия в выражении as ... as, не влияет на то, какое число передается.
big purple cowardly pig ‘большая фиолетовая трусливая свинья’ означает число −8, rich Lord ‘богатый Господин’ означает число 2. От чего зависит, положительное число или отрицательное? Как получаются числа 8 и 2?
Добавление прилагательного в словосочетание соответствует умножению на 2.
Если в каком-то месте пьесы герою (скажем, Ромео) передается число, то оно сохраняется в его «памяти», и позднее его можно использовать с помощью местоимения myself ‘меня’ (если говорит Ромео) или thyself ‘тебя’ (если кто-то говорит с Ромео).
Основные правила языка Shakespeare таковы:
Разберем некоторые части программы-пьесы с точки зрения описанных выше правил:
1. В первой реплике Джульетта передает Ромео значение 2 (Lord ‘Господин’ имеет положительную окраску, к нему добавляется одно прилагательное) и просит его вывести его на экран.
2. Во второй реплике Ромео передает Джульетте значение 2×2×2×2×1 + 2×2×2×1 + (−1) = 23.
3. В первой реплике второго акта Джульетта передает Ромео значение 23 + 2×2×1 + 2×1 = 29. Число 23 появляется, когда Джульетта говорит the sum of myself and ... ‘сумма меня и ...’, апеллируя к переданному ей ранее значению.
4. Во второй реплике второго акта Ромео передает брату Лоренцо число 2×2×2×1 + (−1) = 7.
5. В третьей реплике второго акта брат Лоренцо обращается к Ромео и передает ему число the sum of thyself and a cursed handsome A ‘сумма тебя [то есть Ромео; к моменту данной реплики последний хранит в себе число 29] и проклятого [×2] привлекательного [×2] A’. Вместо A должно стоять существительное, которое определяет знак второго слагаемого. Так как программа выдала число 25, слагаемое должно быть отрицательным (29−4 = 25), значит, на месте A должно стоять слово c отрицательной окраской: devil.
6. В последней реплике как минимум должны присутствовать слова you, open, your, heart — значит, нам нужно шестью словами передать значение 48. Легко понять, что это не получится сделать, если использовать запись через прилагательные и существительные; однако мы можем пользоваться местоимениями и ссылаться на уже сохраненные значения! В Ромео сейчас записано число 25, в Джульетту — число 23; их сумма равна 48. Значит, подходит ответ You the sum of myself and thyself. Open your heart! ‘Ты, сумма меня и тебя! Излей свою душу!’.
Отметим, что ответ, в котором значения Ромео и Джульетты складываются вместе, прекрасно подходит и для счастливого завершения нашей пьесы (в отличие от мрачной концовки в оригинале Шекспира).
Cэр Фредерик Лейтон «Примирение Монтекки и Капулетти» (1855)
Осталось ответить на вопрос задания 4. Ответ ясен из логики работы программы: одновременно на сцене может находиться не более двух персонажей, поскольку программа должна однозначно определять, к кому обращена речь в реплике; если же Джульетта не уйдет со сцены, то в следующей реплике Ромео будет непонятно, обращается ли он к брату Лоренцо или к ней.
Похожи ли языки программирования на человеческие языки? В целом, конечно, нет. Основные различия между ними, пожалуй, заключаются в их функции и происхождении: естественные языки возникли естественным образом и предназначены для передачи информации от человека к человеку, в то время как языки программирования — продукт осознанного человеческого творчества, а информацию они «передают» от человека к компьютеру. Как следствие, устройство языков программирования и естественных языков отличается по ряду аспектов, например:
1. В естественных языках распространены нерегулярности и исключения (им всегда посвящено много времени на уроках русского). В отличие от них, языки программирования устроены очень регулярно, внезапных и нелогичных исключений в них не бывает.
2. В разговоре людей часть информации может искажаться (скажем, в ситуации, когда при произнесении фразы неподалеку проехала фура), однако собеседник всё равно часто в силах понять, что ему было сказано. Это связано, с одной стороны, с возможностью человека достраивать недостающую часть фразы по контексту, а с другой стороны, с избыточностью языка. Свойство избыточности заключается в том, что при произнесении фразы часть информации в предложении может передаваться сразу в нескольких местах. Скажем, когда мы говорим Сообразительные школьники решают сложную задачу, мы передаем информацию о том, что школьников было больше одного, как минимум трижды: с помощью окончания прилагательного -ые множественного числа, окончания -и существительного и финальной части -ют глагола. В языках программирования, напротив, избыточности такого вида мало, а искажение текста программы даже в одном символе может привести к ошибке при ее компиляции (переводе программы на низкоуровневый «язык» компьютера) или запуске.
3. В естественных языках существуют многозначные слова и омонимы, а в языках программирования — нет (иначе как компьютер бы понимал, какое из значений слова имеется в виду? это потребовало бы от создателей языка программирования особых усилий, при этом едва ли сделало бы программирование удобнее, скорее наоборот).
4. На уроках русского языка учат, что бывают повествовательные, вопросительные и побудительные предложения. В языках программирования первых двух типов предложений не бывает: текст программы состоит из команд, то есть, если можно так выразиться, только из побудительных предложений, предписывающих компьютеру, что ему нужно делать.
Несмотря на большое количество существенных различий между языками программирования и человеческими языками, их всё же связывает довольно любопытный мостик — искусственные языки. Искусственные языки, или конланги, придумывались и придумываются людьми, что делает их похожими на языки программирования; тем не менее они обычно разрабатываются для общения людей (или каких-нибудь вымышленных существ, скажем эльфов или гептаподов), что сближает их с естественными языками. В книге [2] («Конструирование языков: От эсперанто до дотракийского») Александр Пиперски выделяет три класса искусственных языков в зависимости от целей их разработки: международные вспомогательные языки создаются для международного общения (например, эсперанто); логические языки представляют собой попытки построения языка, свободного от «недостатков» естественных языков (в первую очередь, от явления многозначности слов и предложений); художественные языки создаются для книг или фильмов, чтобы сделать повествование о вымышленных народах или расах правдоподобнее. К последнему классу автор книги добавляет и искусственные языки, создаваемые просто для развлечения.
Отметим, что в [2] приводится отрывок из словаря «Язык и лингвистика: ключевые понятия» Ларри Траска и Питера Стокуэлла, в котором языки программирования также причисляются к искусственным языкам, а именно к логическим. Нам, с одной стороны, это кажется не совсем правильным, поскольку конечное предназначение логических языков — это все-таки общение людей, а не передача команд компьютеру. С другой стороны, если взять, к примеру, логлан, один из известных логических языков, то, оказывается, что у него и правда много общего с языками программирования. Сторонники этого языка даже разработали компьютерные программы, позволяющие автоматически распознавать предложения на этом языке, — настолько регулярно он устроен. Таким образом, можно считать, что логические языки — это такой промежуточный шаг от естественных языков к языкам программирования.
Как кажется автору данного послесловия, сообщество программистов во многом похоже на сообщество конлангеров — создателей искусственных языков. В частности, язык Shakespeare, с которым вы познакомились, решая задачу, по цели своего создания сопоставим с художественными языками, теми, которые создаются для развлечения. Такой «художественный» язык программирования далеко не единственный: существует целое семейство так называемых эзотерических языков программирования, которые разрабатываются обычно именно для развлечения, в шутку. Приведем несколько забавных примеров:
1. Chef (официальный сайт): язык программирования, в котором программы выглядят как рецепты блюд. Здесь можно найти пример программы на этом языке, печатающей первые 100 чисел Фибоначчи (название этой программы на русский язык переводится «Числа Фибоначчи под карамельным соусом»).
2. Malbolge: язык программирования, названный в честь восьмого круга ада у Данте, разработанный специально, чтобы писать программы на нем было как можно сложнее. Три самых ярких черты этого языка: а) программа переписывает себя в процессе выполнения, б) при выполнении операции учитывается место в памяти компьютера, в котором лежит символ данной операции, в) программа работает в троичной системе счисления. Автор этого языка не написал на нем ни одной программы (см. интервью с Беном Олмстедом), а программа на этом языке, которая всего лишь выводит на экран фразу Hello world ‘Привет, мир’, была найдена через два года после создания Malbolge — и то не человеком, а, автоматическим способом, компьютером. Вот как эта программа выглядит:
(=<`:9876Z4321UT.-Q+*)M'&%$H"!~}|Bzy?=|{z]KwZY44Eq0/{mlk**hKs_dG5[m_BA{?-Y;;Vb'rR5431M}/.zHGwEDCBA@98\6543W10/.R,+O<
3. Whitespace: язык программирования, в котором используются только символы пробела, абзаца и табуляции, а остальные символы игнорируются. Шутка создателей языка заключается в том, что обычно языки программирования, напротив, игнорируют эти три символа; в программе на языке Python, скажем, неважно, поставил ли разработчик между командами один пробел или два.
Вот как выглядит программа на языке Whitespace, выводящая на экран фразу Hello world (в ней выделены цветом символы пробела и табуляции):
4. Velato: язык программирования, в котором программы представляют собой музыкальные произведения. Так, например, выглядит программа, выводящая на экран Hello world, в нотной записи:
А здесь эту программу можно послушать.
На самом деле, эзотерических языков программирования гораздо больше: на сайте esolangs.org/wiki представлено порядка 2000 таких языков (для сравнения, естественных языков порядка 7000). Заинтересованный читатель сможет найти на этом сайте язык Hexagony, в котором программы записываются в виде шестиугольников; язык Ook!, в котором команды походят на крики орангутанга; язык Piet, программы которого выглядят как абстрактная живопись; прекрасный язык Fractran, изобретенный математиком Джоном Конвеем, в котором программы записываются в виде цепочек дробей; и многие-многие другие необычные изобретения программистов-эзотериков. Приглашаем вас погрузиться в этот фантастический и немного дикий мир!
Чем среди 2000 эзотерических языков программирования нас привлек именно язык Shakespeare? Во-первых, бесспорно, своей эстетичностью, а также тем, что команды в нем представляют обычные, грамматически правильные английские предложения.
Во-вторых, чему и была посвящена задача, — весьма необычным способом записи чисел. В лингвистике отдельной и весьма занимательной темой является изучение систем числительных в языках мира. Во многих языках числительные строятся на базе десятичной системы счисления: например, в русском языке существуют отдельные слова для чисел от 1 до 10, а какое-нибудь число побольше, скажем 231, раскладывается по степеням десяти: 231 = 2×100 + 3×10 + 1 — и на основе этого разложения формируется числительное двести тридцать один. Выбор именно числа 10 для основания системы числительных связан с простой биологической особенностью человека — наличием у него ровно десяти пальцев на руках, которыми он может считать. Несмотря на это существует немало языков, основанных на других системах счисления. Скажем, в грузинском языке счет идет не по десяткам, а по двадцаткам: так, число 74 на грузинский переводится как самоцдатотхмэти, при этом 3 переводится как сами, 20 — как оци, а 14 — как тотхмэти. Получается, с точки зрения грузинского языка 74 = 3×20 + 14. Бывают и другие системы числительных, например основанные на двенадцатеричной или шестеричной системе счисления.
В языке Shakespeare, что абсолютно нехарактерно для естественных языков, используется двоичная система счисления. Чтобы передать на этом языке, например, число 38, надо разложить его по степеням двойки и после этого записать каждое из слагаемых в разложении с помощью существительного и прилагательных. Разложение выглядит так: 38 = 32 + 4 + 1 = 25 + 22 + 1. На язык Shakespeare его можно переписать в виде the sum of a charming noble cursed tiny old King (32) and the sum of a mighty little hero (4) and an angel (1) ‘сумма очаровательного благородного проклятого крошечного старого Короля и суммы могущественного маленького героя и ангела’. Двоичная система счисления, хотя и не встречается в естественных языках, повсеместно используется в компьютерах, где базовыми значениями являются всего два — 0 и 1. Думаем, именно этим был вдохновлен выбор данной системы счисления в языке Shakespeare.
В заключение стоит добавить, что приведенная в условии задача отражает далеко не все возможности языка Shakespeare: помимо передачи чисел друг другу и вывода их на экран, персонажи могут запоминать в себе сразу несколько чисел, а потом выдавать их по очереди из памяти (полную документацию этого языка программирования на английском языке можно найти на сайте разработчиков: shakespearelang.sourceforge.net). Числа хранятся в персонажах в виде стека, то есть если персонажа по очереди попросили запомнить числа 2, 10, 15, а потом попросили выдать два числа, то он сперва вернет 15, а потом 10, при этом в памяти останется 2. Также в языке Shakespeare есть условные операторы (то есть команды вида если условие А верно, то сделай Б; если А неверно, то сделай В) и возможность создавать циклы, что делает его сопоставимым с полноценными языками программирования. Шекспиру такое и не снилось!
Задача использовалась на IV Устной олимпиаде по лингвистике НИУ ВШЭ — 2019.
Литература:
[1] А. Е. Пентус, М. Р. Пентус. Теория формальных языков: Учебное пособие — М.: Изд-во ЦПИ при механико-математическом ф-те МГУ, 2004. — 80 с.
[2] А. Пиперски. Конструирование языков: От эсперанто до дотракийского. — М.: ООО «Альпина Паблишер», 2017. — 270 с.
Cэр Фрэнк Бернард Дикси «Ромео и Джульетта» (1884)