Lipograma “quine”

26

Tarefa

  1. Pegue um único caractere Unicode como entrada.
  2. Saída de um programa no mesmo idioma que também obedece a esta especificação, mas que não contém o caractere de entrada.
  3. Se o seu programa for executado com a entrada a , e o programa de saída for executado com a entrada b , o programa que ele emitir será PERMITIDO para conter o caractere a . No entanto, b ainda não está autorizado a aparecer neste programa. Em outras palavras, apenas a entrada na encarnação mais recente do programa é proibida de aparecer.
  4. Independentemente do que o título possa dizer, aplicam-se regras padrão de quine.

O programa mais curto vence. O programa deve ter pelo menos um byte.

Exemplo

Se o programa for ABCD. (# é um comentário)

> 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

Onde slangiestá um intérprete para uma linguagem fictícia.

Akangka
fonte
Esse desafio não seria menos detalhado? Várias usam palavras para nomes de instruções, por isso seria muito difícil e / ou impossível evitar caracteres como e.
LegionMammal978
2
É muito difícil escrever em inglês sem o eGadsby.
Akangka
Estou assumindo que não há funções quine?
Mama Fun Roll

Respostas:

24

CJam, 45 41 38 35 bytes

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

Se o caractere de entrada não for um dos caracteres "$&)+,/:?HOX\_`el{}, este programa imprimirá a seguinte versão ligeiramente modificada de si mesma. Experimente online!

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

Caso contrário, o programa imprime a seguinte versão ofuscada da modificação. Experimente online!

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

Observe que alguns dos caracteres não são imprimíveis. Experimente online!

Como 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-~"

No primeiro programa de saída possível, evitamos ~usá-lo no outro programa. Portanto, em vez de _~, o programa modificado termina com OX$_?, que funciona da seguinte maneira.

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, no programa de saída 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]

agrupa todos esses caracteres em uma matriz, pressionando a sequência a seguir.

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

If- subtrai 18 de cada código de caractere, pressionando a string

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

qual ~avalia.

Dennis
fonte
18

JavaScript (ES6), 356 340 327 308 303 263

Agora, usando Function`...```o 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()

A função se comporta em um dos três programas possíveis:

  1. O primeiro programa chama eval uma string literal contendo o código da função com cada caractere escapado como um valor octal.

    eval ('\ 146 \ 165 ...')
  2. O segundo programa redireciona o navegador para um javascript: URL que contém o código da função com cada URL de caractere codificado. Esta é a única maneira que eu poderia pensar em avaliar o código sem usar parênteses. Ele também escapa as letras em 'eval'.

    window ["\ x6coc \ x61tion"] ["hr \ x65f"] = "j \ x61 \ x76 \ x61script:% 66% 75 ..."
  3. O último programa é dolorosamente longo. Ele cria o código da função adicionando um (+9-8 ) de cada vez para obter o código de cada caractere. Isso é para evitar o uso dos dígitos octais.

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

O programa correto é indexado pesquisando uma string cuidadosamente construída para o caractere de entrada:

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

Aqui está uma versão não testada e não testada. Pode não funcionar devido a novas linhas na fonte.

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
fonte
function f(){ ... };f()pode ser (f=_=>{ ... })(). Aqui está um exemplo: es6fiddle.net/iiz2nq0l
Ismael Miguel
Ainda melhor: f=(_=prompt())=>...;f(). A entrada é armazenada como _.
Mama Fun Roll
Além disso, não há necessidade de console.log, a saída da função é boa.
Mama Fun Roll
Não usará Function`[code]`.call``;trabalho para você, em vez de redirecionar? Aqui está um exemplo de trabalho: es6fiddle.net/ij023v49 (See No? evil()Erm, eu quero dizer! eval()...)
Ismael Miguel
Bem, você aprendeu algo hoje. Esteja ciente de que o thisobjeto será essa sequência de modelo vazia. Ele se baseia no Functionconstrutor, que permite criar uma função, em vez de executar eval(). A função terá o código contido no primeiro parâmetro. Eu uso muito para obter o real window, usando Function('return this')(). Como você não pode usar (), eu abusei um pouco da gentileza do ES6 para tentar cuspir uma função utilizável que você pode executar sem (). Para isso, você precisa do .call()método, que chama a função com um novo thisobjeto.
Ismael Miguel