7 , 410 символов, 154 байта в кодировке 7, 0 букв = оценка 154
55104010504200144434451510201304004220120504005434473340353241135014335450302052254241052253052244241052335452241114014241310052340435303052335442302052335500302052335430302052313340435303135014243241310335514052312241341351052302245341351525755102440304030434030421030442030424030455733413512410523142410523030523112411350143355142410523414252410523102410523002410523413342411145257551220304010420030455741403
Попробуйте онлайн!
В вызове, который не любит использовать буквы, какой язык лучше использовать, чем язык, состоящий только из цифр?
Это полная программа, которая завершается сбоем, так что в stderr есть посторонний вывод, но stdout верен.
объяснение
Программа 7 на своей первой итерации просто помещает в стек несколько элементов (поскольку из 12 команд, существующих в 7, только 8 из них могут быть представлены в исходной программе, а эти 8 предназначены для написания кода поместить определенные структуры данных в стек). Эта программа не использует 6команду (которая является самым простым способом создания вложенных структур, но в остальном не стремится буквально появиться в исходной программе), поэтому только 7команды определяют структуру; 7помещает новый пустой элемент в верхнюю часть стека (тогда как команды 0… 5просто добавляются в верхнюю часть стека). Таким образом, мы можем добавить пробел в программу, чтобы показать ее структуру:
551040105042001444344515102013040042201205040054344 7
33403532411350143354503020522542410522530522442410523354522411140142413100523
40435303052335442302052335500302052335430302052313340435303135014243241310335
514052312241341351052302245341351525 7
55102440304030434030421030442030424030455 7
33413512410523142410523030523112411350143355142410523414252410523102410523002
41052341334241114525 7
551220304010420030455 7
41403
Элементы в конце программы помещаются последними, поэтому они находятся на вершине стека в начале второй итерации. На этой итерации и на всех последующих итерациях интерпретатор 7 автоматически делает копию вершины стека и интерпретирует ее как программу. Литерал 41403выдвигает (не-литеральный, живой код) 47463(7 имеет 12 команд, но только у 8 из них есть имена, поэтому я использую жирный шрифт, чтобы показать код, и не жирный, чтобы показать литерал, который генерирует этот код, то есть например, 4это команда, которая добавляет 4к верхнему элементу стека). Итак, программа, которая запускается на второй итерации, такова 47463. Вот что это делает:
47463
4 Поменяйте местами два верхних элемента стека, добавьте пустой элемент между ними
7 Добавьте пустой элемент стека в верхнюю часть стека
4 Поменяйте местами два верхних элемента стека, добавьте пустой элемент между ними
6 Определите, какие команды будут генерировать верхний элемент стека;
добавить это к элементу ниже (и вытолкнуть старую вершину стека)
3 Выведите верхний элемент стека, вставьте элемент ниже
Это легче понять, если мы посмотрим, что происходит со стеком:
- ... d Ĉ б а
47463 (код для запуска: 47463)
- ... d с б опорожнить а (код для запуска: )
47463 7463
- ... d с б опорожнить в пустой (код для запуска: )
47463 463
- ... d с б пустой пустой пустой а (код для запуска: )
47463 63
- ... d с б пустой пустой « в » (код для запуска: )
47463 3
- … D c b пусто (код для запуска: пусто )
47463
Другими словами, мы берем верхнюю часть стека a , выясняем, какой код, скорее всего, его сгенерировал, и выводим этот код. Интерпретатор 7 автоматически выталкивает пустые элементы из верхней части стека в конце итерации, поэтому мы в итоге получаем 47463обратную вершину стека, как в исходной программе. Должно быть легко увидеть, что происходит дальше: мы в конечном итоге перелистываем каждый элемент стека один за другим, выводим их все до тех пор, пока стек не опустится и программа не выйдет из строя. Итак, мы в основном создали простой цикл вывода, который просматривает исходный код программы, чтобы определить, что выводить (мы не выводим структуры данных, которые были помещены в стек нашей 0…5команды, мы вместо этого воссоздаем, какие команды были использованы, посмотрев, какие структуры были созданы, и вывеся их). Таким образом, первая часть данных выводится 551220304010420030455(исходный код, который генерирует элемент стека второй сверху), вторая - 3341351…114525(исходный код, который генерирует элемент стека третий сверху) и так далее.
Очевидно, однако, что эти части исходного кода не выводятся в незашифрованном виде. 7 содержит несколько разных предметно-ориентированных языков для кодирования вывода; после выбора языка, специфичного для домена, он остается в использовании до тех пор, пока не будет явно очищен, но если еще не выбран ни один из языков, первая цифра в коде вывода определяет, какой из языков использовать. В этой программе используются только два языка: 551и 3.
551это довольно просто: в основном это старый код Бодо / телетайпа, используемый для передачи букв по телетайпам в виде 5-битного набора символов, но измененный, чтобы сделать все буквы строчными. Итак, первый кусок кода, который будет выводиться, декодируется следующим образом:
551 22 03 04 01 04 20 03 04 55
c a SP e SP n a SP reset output format
Как видно, мы подгоняем каждый символ в две восьмеричные цифры, что является довольно приличным коэффициентом сжатия. Пары цифр в диапазоне 0-5 дают нам 36 возможностей, в отличие от 32 возможностей, которые нужны Бодо, поэтому оставшиеся четыре используются для специальных команд; в этом случае, 55в конце очищается запомненный выходной формат, что позволяет нам использовать другой формат для следующей части вывода, которую мы производим.
3Концептуально даже проще, но с изюминкой. Основная идея состоит в том, чтобы взять группы из трех цифр (опять же, в диапазоне 0-5, так как это те цифры, для которых мы можем гарантировать, что мы можем воссоздать исходный исходный код из его выходных данных), интерпретировать их как трехзначные число в базе 6, и просто выведите его как байт в двоичном виде (что позволяет нам выводить многобайтовые символы в желаемом выводе, просто выводя несколько байтов). Однако поворот заключается в том, что в базе 6 имеется только 216 трехзначных чисел (с возможными ведущими нулями), но 256 возможных байтов. 7 обходит это, связывая числа от 332₆ = 128₁₀ и выше до двух разных байтов; 332может выводить либо байт 128 или 192, 333либо байт 129 или 193 и т. д., до 515которых выводится либо байт 191, либо 255.
Как программа узнает, какую из двух возможностей вывести? Для 520явного управления этим можно использовать тройки цифр сверху вниз, но в этой программе нам не нужно: 7 по умолчанию выбирает все неоднозначные байты таким образом, чтобы вывод был действительным UTF-8! Оказывается, что всегда есть только один способ сделать это, поэтому, пока мы хотим UTF-8 (и мы делаем в этом случае), мы можем просто оставить это двусмысленным, и программа все равно работает.
Конец каждого из 3…разделов - это 525, который сбрасывает выходной формат, позволяя нам вернуться к 551следующему разделу.
as - или нет, в зависимости от того, сколько букв, которые потребуются, потому что 20 символов - это действительно большое наказание (хотя, когда все остальное оценивается байтами, это не совсем хорошо определено ...)!