Whitespace - kenrube/Esopoly GitHub Wiki
Whitespace - полушуточный язык программирования, исходник на котором можно встроить в любой другой: используя только символы пробела, табуляции и перевода строки, он прячется у всех на виду :) Ознакомиться с синтаксисом языка можно на официальной странице.
Алгоритм вывода фразы Whitespace program
прост: заталкиваем (push) все символы, начиная с конца, в стек, затем по одному извлекаем их (pop) и выводим на печать. Удобства ради обозначим пробел как -
, символ табуляции как >
, а символ перевода строки как v
.
- Вызываем
--
, что позволит нам затолкать идущее следом число (битовое представление символа) на вершину стека.-
в числе означает0
,>
-1
. Заканчивается число переводом строкиv
. - После того, как все числа окажутся в стеке, для вывода каждого из них вызываем
>v--
. Согласно спецификации, эта последовательность инструкций извлекает и выводит на печать символ с вершины стека. - После вывода всех символов вызываем
vvv
, что означает конец программы.
Пишем исходник в псевдокоде:
-- ->>->>->v push 'm'(01101101) to stack
-- ->>---->v push 'a'(01100001)
-- ->>>-->-v push 'r'(01110010)
-- ->>-->>>v push 'g'(01100111)
-- ->>->>>>v push 'o'(01101111)
-- ->>>-->-v push 'r'(01110010)
-- ->>>----v push 'p'(01110000)
-- -->-----v push ' '(00100000)
-- ->>-->->v push 'e'(01100101)
-- ->>--->>v push 'c'(01100011)
-- ->>---->v push 'a'(01100001)
-- ->>>----v push 'p'(01110000)
-- ->>>-->>v push 's'(01110011)
-- ->>-->->v push 'e'(01100101)
-- ->>>->--v push 't'(01110100)
-- ->>->-->v push 'i'(01101001)
-- ->>->---v push 'h'(01101000)
-- ->->->>>v push 'W'(01010111)
>v-- pop & print 'W'
>v-- pop & print 'h'
>v-- pop & print 'i'
>v-- pop & print 't'
>v-- pop & print 'e'
>v-- pop & print 's'
>v-- pop & print 'p'
>v-- pop & print 'a'
>v-- pop & print 'c'
>v-- pop & print 'e'
>v-- pop & print ' '
>v-- pop & print 'p'
>v-- pop & print 'r'
>v-- pop & print 'o'
>v-- pop & print 'g'
>v-- pop & print 'r'
>v-- pop & print 'a'
>v-- pop & print 'm'
vvv finish
Или то же самое на настоящем Whitespace (вид после встраивания в общий исходник; отбросьте head и tail, если хотите увидеть только аналог псевдокода):
head
head
tail
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
--//--
Опробовать можно в онлайн-интерпретаторе.
Почему исходник столь сильно увеличился после встраивания? Я перебрал множество вариантов того, чтобы общий исходный код выглядел как можно более эстетично (рассчитывая, разумеется, на размер таба = 1), и в итоге пришел к тому, что неплохо в общей канве смотрится смайл X-P
, воссозданный из исходного кода на Whitespace. X
сформирован из кода заталкивания символов в стек, -
- из кода извлечения и вывода. P
добавился за компанию и, хоть и состоит тоже из смеси пробелов и табов, на самом деле не выполняет никаких действий в контексте Whitespace - наша программа уже закончила свое выполнение после 3 переводов строки подряд. Точно так же позже добавилась и надпись ESOTERIC POLYGLOT
- слишком много места оставалось без граффити :)
Встраивать в общий исходник пока не будем, сделаем это на последнем этапе.