Липограмма «Куайн»


26

задача

  1. Возьмите один символ Unicode в качестве ввода.
  2. Выведите программу на том же языке, который также соответствует этой спецификации, но не содержит вводимый символ.
  3. Если ваша программа запускается с помощью ввода a , а затем выходная программа запускается с помощью ввода b , то программе, которую она выводит, разрешено содержать символ a . Однако b все еще не разрешено появляться в этой программе. Другими словами, только вход в самое последнее воплощение программы запрещено появляться.
  4. Независимо от того, что заголовок может сказать, применяются стандартные правила Квина.

Кратчайшая программа выигрывает. Программа должна быть длиной не менее одного байта.

пример

Если программа ABCD. (# это комментарий)

> slangi "ABCD"
A
EBCD          # "FBCD" "JGGJ" "UGDKJGDJK" are all OK
> slangi "EBCD"
C
ABGD          # "EBGD" "UIHDAIUTD" are all OK
> slangi "ABGD"
B
AFCD
> slangi "AFCD"
Z
ABCD

Где slangiпереводчик для вымышленного языка.


Разве это не бросило бы вызов менее многословным языкам? Некоторые используют слова для имен инструкций, поэтому было бы очень трудно и / или невозможно избежать таких символов, как e.
LegionMammal978

2
Без него очень трудно писать по-английски e, но это делает Гэдсби.
Akangka

Я предполагаю, что нет функций Quine?
Mama Fun Roll

Ответы:


24

CJam, 45 41 38 35 байт

{`"OX$_?"+_l&{{H)+`}/"\He,}":)}&}_~

Если вводимый символ не является ни одним из символов "$&)+,/:?HOX\_`el{}, эта программа печатает следующую, слегка измененную версию себя. Попробуйте онлайн!

{`"OX$_?"+_l&{{H)+`}/"\He,}":)}&}OX$_?

В противном случае программа печатает следующую обфусцированную версию модификации. Попробуйте онлайн!

''r'4'a'j'6'q'Q'4'='q'~'8'''Z';'='r''A'4'n'Z'w'>''4'L';''8''a'j'6'q'Q]If-~

Обратите внимание, что некоторые символы непечатаемы. Попробуйте онлайн!

Как это работает

{`"OX$_?"+_l&{{H)+`}/"\He,}":)}&}_~

{                               }    Define a code block.
                                 _~  Push a copy and execute the copy.
 `                                   Push a string representation of the block.
  "OX$_?"                            Push that string.
         +_                          Concatenate and push a copy.
           l&                        Intersect the copy with the input.
             {                }&     If the intersection is non-empty:
              {    }/                  For each character of the concat. strings:
               H)                        Push 18.
                 +                       Add it to the character.
                  `                      Inspect; turn 'c into "'c".
                     "He,}"            Push that string.
                           :)          Increment each char. Pushes "If-~"

В первой возможной программе вывода мы избегаем использовать ~ее для использования в другой программе. Поэтому вместо _~модифицированной программы заканчивается OX$_?, что работает следующим образом.

O        Push "" (falsy).
 X$      Push a copy of the code block.
   _     Push yet another copy.
    ?    Ternary if; since "" is falsy, execute the second copy.

Наконец, в оставшейся выходной программе

''r'4'a'j'6'q'Q'4'='q'~'8'''Z';'='r''A'4'n'Z'w'>''4'L';''8''a'j'6'q'Q]

оборачивает все эти символы в массив, поэтому выдвигает следующую строку.

"'4aj6qQ4=q~8'Z;=r'104nZw>'4L;'8'j6qQ"

If- вычитает 18 из каждого кода символа, нажимая строку

"{`\"OX$_?\"+_l&{{H)+`}/\"\He,}\":)}&}OX$_?"

который ~оценивает.


18

JavaScript (ES6), 356 340 327 308 303 263

Теперь используем Function`...```для второй программы:

f=(b=y=>[for(x of`f=${f};f()`)x.charCodeAt().toString(y).toUpperCase()])=>alert([`eval('\\${b(8).join('\\')}')`,`eval(String.fromCharCode(${b(10).map(x=>'+9-8'.repeat(x))}))`,'Function`\\x'+b(16).join('\\x')+'```'][1+"0e1v2a3l4(5'6'7)\\".indexOf(prompt())%2]);f()

Функция упаковывает себя в одну из трех возможных программ:

  1. Первая программа вызывает evalстроковый литерал, содержащий код функции, причем каждый символ экранируется как восьмеричное значение.

    Eval ( '\ 146 \ 165 ...')
  2. Вторая программа перенаправляет браузер на javascript:URL-адрес, содержащий код функции с кодированным URL-адресом каждого символа. Это единственный способ оценить код без использования скобок. Это также ускользает от букв в 'Eval'.

    Окно [ "\ x6coc \ x61tion"] [ "ч \ x65f"] = "J \ x61 \ x76 \ x61script:% 66% 75 ..."
  3. Последняя программа мучительно длинная. Он строит код функции, добавляя по одному ( +9-8) за раз, чтобы получить код каждого символа. Это делается для того, чтобы не использовать восьмеричные цифры.

    Eval (String.fromCharCode (+ 9-8 + 9-8 + 9-8 + 9-8 ...))

Правильная программа индексируется путем поиска тщательно сконструированной строки для входного символа:

[`program_1`,`program_3`,`program_2`][1+"0e1v2a3l4(5'6'7)\\".indexOf(prompt())%2]

Вот неопробованная, не проверенная версия. Это может не сработать из-за новых строк в источнике.

function f() {
    // convert source code of current function to bytes
    var bytes = Array.map(f + 'f()', x => x.charCodeAt());

    // pack this function's code in one of three possible programs,
    // depending on the input
    var input = prompt();

    // PROGRAM 1 - only contains characters: eval(')01234567\
    // eval('\146\165...')
    var source = "eval('\\" + bytes.map(x => x.toString(8)).join('\\') + "')";

    // PROGRAM 2 - doesn't contain characters: eval('')
    // window["\x6coc\x61tion"]["hr\x65f"]="j\x61\x76\x61script:%66%75..."
    // -> window["location"]["href"] = "javascript:..."
    if ("eval(')".includes(input)) {
        source = 'window["\\x6coc\\x61tion"]["hr\\x65f"]="j\\x61\\x76\\x61script:%';
        source += bytes.map(x => x.toString(16).toUpperCase()).join('%') + '"';
    }

    // PROGRAM 3 - doesn't contain characters: 01234567\
    // eval(String.fromCharCode(+9-8+9-8+9-8+9-8...))
    if ('01234567\\'.includes(input)) {
        source = "eval(String.fromCharCode(";
        source += bytes.map(x => '+9-8'.repeat(x)).join(',') + '))';
    }

    console.log(source);
}
f()

function f(){ ... };f()может быть (f=_=>{ ... })(). Вот пример: es6fiddle.net/iiz2nq0l
Исмаэль Мигель

Еще лучше: f=(_=prompt())=>...;f(). Ввод сохраняется как _.
Mama Fun Roll

Кроме того, нет необходимости в console.log, функция вывода в порядке.
Mama Fun Roll

Разве вы не будете использовать Function`[code]`.call``;работу вместо перенаправления? Вот рабочий пример: es6fiddle.net/ij023v49 (видите? Нет evil()! Эмм, я имею в виду eval()...)
Исмаэль Мигель

Ну, ты кое-что узнал сегодня. Просто знайте, что thisобъект будет той пустой строкой шаблона. Он опирается на Functionконструктор, который позволяет создавать функции, а не запускать eval(). Функция будет иметь код, содержащийся в первом параметре. Я использую это много, чтобы получить реальное window, используя Function('return this')(). Так как вы не можете использовать (), я немного злоупотребил добротой ES6, пытаясь выплюнуть полезную функцию, без которой вы можете работать (). Для этого вам нужен .call()метод, который вызывает функцию с новым thisобъектом.
Исмаэль Мигель
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.