Lipogramme «quine»

26

Tâche

  1. Prenez un seul caractère Unicode en entrée.
  2. Afficher un programme dans le même langage qui obéit également à cette spécification, mais qui ne contient pas le caractère d'entrée.
  3. Si votre programme est exécuté avec l'entrée a , puis le programme de sortie est ensuite exécuté avec l'entrée b , le programme qu'il génère est autorisé à contenir le caractère a . Cependant, b n'est toujours pas autorisé à apparaître dans ce programme. En d'autres termes, seule l'entrée dans la dernière incarnation du programme est interdite.
  4. Indépendamment de ce que le titre peut dire, les règles de quine standard s'appliquent.

Le programme le plus court gagne. Le programme doit comporter au moins un octet.

Exemple

Si le programme est ABCD. (# est un commentaire)

> 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

slangiest un interprète pour une langue fictive.

Akangka
la source
Ce défi ne serait-il pas un langage moins verbeux? Plusieurs utilisent des mots pour les noms d'instructions, il serait donc très difficile et / ou impossible d'éviter les caractères tels que e.
LegionMammal978
2
Il est très difficile d'écrire en anglais sans e, pourtant Gadsby le fait.
Akangka
Je suppose qu'il n'y a pas de fonctions quine?
Mama Fun Roll

Réponses:

24

CJam, 45 41 38 35 octets

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

Si le caractère d'entrée n'est aucun des caractères "$&)+,/:?HOX\_`el{}, ce programme imprime la version suivante, légèrement modifiée de lui-même. Essayez-le en ligne!

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

Sinon, le programme imprime la version obscurcie suivante de la modification. Essayez-le en ligne!

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

Notez que certains des caractères ne sont pas imprimables. Essayez-le en ligne!

Comment ça marche

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

Dans le premier programme de sortie possible, nous évitons d'utiliser ~pour pouvoir l'utiliser dans l'autre programme. Par conséquent, au lieu de _~, le programme modifié se termine par OX$_?, qui fonctionne comme suit.

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

Enfin, dans le programme de sortie restant,

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

encapsule tous ces caractères dans un tableau, poussant donc la chaîne suivante.

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

If- soustrait 18 de chaque code de caractère, en poussant la chaîne

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

que ~l'évalue.

Dennis
la source
18

JavaScript (ES6), 356 340 327 308 303 263

Utilisant maintenant Function`...```pour le deuxième programme:

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 fonction s'emballe dans l'un des trois programmes possibles:

  1. Le premier programme fait appel evalà un littéral de chaîne contenant le code de la fonction avec chaque caractère échappé comme valeur octale.

    eval ('\ 146 \ 165 ...')
  2. Le deuxième programme redirige le navigateur vers une javascript:URL contenant le code de la fonction avec chaque URL de caractère encodée. C'est la seule façon dont je pouvais penser pour évaluer le code sans utiliser de parenthèses. Il échappe également aux lettres en «eval».

    fenêtre ["\ x6coc \ x61tion"] ["hr \ x65f"] = "j \ x61 \ x76 \ x61script:% 66% 75 ..."
  3. Le dernier programme est douloureusement long. Il construit le code de la fonction en ajoutant un ( +9-8) à la fois pour obtenir chaque code de caractère. Ceci afin d'éviter d'utiliser les chiffres octaux.

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

Le programme correct est indexé en recherchant une chaîne soigneusement construite pour le caractère d'entrée:

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

Voici une version non golfée et non testée. Cela pourrait ne pas fonctionner en raison de nouvelles lignes dans la source.

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
la source
function f(){ ... };f()peut être (f=_=>{ ... })(). Voici un exemple: es6fiddle.net/iiz2nq0l
Ismael Miguel
Mieux encore: f=(_=prompt())=>...;f(). L'entrée est stockée sous _.
Mama Fun Roll
En outre, pas besoin de console.log, la sortie de la fonction est très bien.
Mama Fun Roll
N'utilisera pas le Function`[code]`.call``;travail pour vous, au lieu de rediriger? Voici un exemple de travail: es6fiddle.net/ij023v49 (Voir? Non evil()! Erm, je veux dire eval()...)
Ismael Miguel
Eh bien, vous avez appris quelque chose aujourd'hui. Sachez simplement que l' thisobjet sera cette chaîne de modèle vide. Il repose sur le Functionconstructeur, qui vous permet de créer une fonction, au lieu de l'exécuter eval(). La fonction aura le code contenu dans le premier paramètre. Je l'utilise beaucoup pour obtenir le vrai window, en utilisant Function('return this')(). Comme vous ne pouvez pas l'utiliser (), j'ai abusé de la gentillesse d'ES6 pour essayer de cracher une fonction utilisable sans laquelle vous pouvez exécuter (). Pour cela, vous avez besoin de la .call()méthode, qui appelle la fonction avec un nouvel thisobjet.
Ismael Miguel