Lipograma "quine"

26

Tarea

  1. Tome un solo carácter Unicode como entrada.
  2. Imprime un programa en el mismo lenguaje que también obedece esta especificación, pero que no contiene el carácter de entrada.
  3. Si el programa se ejecuta con la entrada de una , y luego el programa de salida se ejecute con la entrada b , entonces el programa se emite se PERMITIDA para contener el carácter de una . Sin embargo, b todavía no puede aparecer en este programa. En otras palabras, solo está prohibido que aparezca la entrada en la encarnación más reciente del programa.
  4. Independientemente de lo que diga el título, se aplican las reglas estándar de quine.

El programa más corto gana. El programa debe tener al menos un byte de largo.

Ejemplo

Si el programa es ABCD. (# es un comentario)

> 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

¿Dónde slangiestá un intérprete para un lenguaje ficticio?

Akangka
fuente
¿No desafiaría esto a lenguas menos detalladas? Varios usan palabras para nombres de instrucciones, por lo que sería muy difícil y / o imposible evitar caracteres como e.
LegionMammal978
2
Es muy difícil escribir en inglés sin él e, pero Gadsby lo hace.
Akangka
¿Asumo que no hay funciones quine?
Mama Fun Roll

Respuestas:

24

CJam, 45 41 38 35 bytes

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

Si el carácter de entrada no es ninguno de los caracteres "$&)+,/:?HOX\_`el{}, este programa imprime la siguiente versión ligeramente modificada de sí mismo. Pruébalo en línea!

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

De lo contrario, el programa imprime la siguiente versión ofuscada de la modificación. Pruébalo en línea!

''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-~

Tenga en cuenta que algunos de los caracteres no se pueden imprimir. Pruébalo en línea!

Cómo funciona

{`"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-~"

En el primer programa de salida posible, evitamos usarlo ~para poder usarlo en el otro programa. Por lo tanto, en lugar de _~, el programa modificado termina con OX$_?, que funciona de la siguiente manera.

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

Finalmente, en el programa de salida restante,

''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]

envuelve todos esos caracteres en una matriz, por lo tanto, empuja la siguiente cadena.

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

If- resta 18 de cada código de caracteres, empujando la cadena

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

que ~el evalúa.

Dennis
fuente
18

JavaScript (ES6), 356 340 327 308 303 263

Ahora usando Function`...```para el segundo programa:

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()

La función se empaqueta en uno de los tres posibles programas:

  1. El primer programa invoca evalun literal de cadena que contiene el código de la función con cada carácter escapado como un valor octal.

    eval ('\ 146 \ 165 ...')
  2. El segundo programa redirige el navegador a una javascript:URL que contiene el código de la función con cada URL de caracteres codificada. Esta es la única forma en que podría pensar para evaluar el código sin usar paréntesis. También escapa a las letras en 'eval'.

    ventana ["\ x6coc \ x61tion"] ["hr \ x65f"] = "j \ x61 \ x76 \ x61script:% 66% 75 ..."
  3. El último programa es dolorosamente largo. Crea el código de la función agregando uno ( +9-8) a la vez para obtener cada código de caracteres. Esto es para evitar el uso de los dígitos octales.

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

El programa correcto se indexa buscando una cadena cuidadosamente construida para el carácter de entrada:

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

Aquí hay una versión no probada y sin golf. Es posible que no funcione debido a las nuevas líneas en la fuente.

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()
grc
fuente
function f(){ ... };f()puede ser (f=_=>{ ... })(). Aquí hay un ejemplo: es6fiddle.net/iiz2nq0l
Ismael Miguel
Aún mejor: f=(_=prompt())=>...;f(). La entrada se almacena como _.
Mama Fun Roll
Además, no se necesita console.log, la salida de la función está bien.
Mama Fun Roll
¿No utilizará el Function`[code]`.call``;trabajo para usted, en lugar de redirigir? Aquí hay un ejemplo de trabajo: es6fiddle.net/ij023v49 (¿Ves? evil()¡ No ! Erm, quiero decir eval()...)
Ismael Miguel
Bueno, has aprendido algo hoy. Solo tenga en cuenta que el thisobjeto será esa cadena de plantilla vacía. Se basa en el Functionconstructor, que le permite crear una función, en lugar de ejecutarla eval(). La función tendrá el código contenido dentro del primer parámetro. Lo uso mucho para obtener lo real window, usando Function('return this')(). Como no puede usar (), he abusado un poco de la amabilidad de ES6 para tratar de escupir una función utilizable sin la que pueda ejecutar (). Para eso, necesita el .call()método, que llama a la función con un nuevo thisobjeto.
Ismael Miguel