Lipogramm "Quine"

26

Aufgabe

  1. Nehmen Sie ein einzelnes Unicode-Zeichen als Eingabe.
  2. Geben Sie ein Programm in derselben Sprache aus, die auch dieser Spezifikation entspricht, jedoch kein Eingabezeichen enthält.
  3. Wenn Ihr Programm mit Eingabe ausgeführt wird , ein , und dann wird das Ausgabeprogramm dann mit Eingang laufen b , dann wird das Programm es gibt ist ERLAUBT Zeichen enthalten ein . Es ist jedoch weiterhin nicht gestattet , dass b in diesem Programm erscheint. Mit anderen Worten, nur die Eingabe in die letzte Inkarnation des Programms ist verboten.
  4. Unabhängig von der Überschrift gelten die üblichen Regeln für Quine.

Kürzeste Sendung gewinnt. Das Programm muss mindestens ein Byte lang sein.

Beispiel

Wenn das Programm ABCD ist. (# ist ein Kommentar)

> 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

Wo slangiist ein Dolmetscher für eine fiktive Sprache.

Akangka
quelle
Wäre das nicht eine Herausforderung für weniger ausführliche Sprachen? Einige verwenden Wörter für Anweisungsnamen, so dass es sehr schwierig und / oder unmöglich wäre, Zeichen wie zu vermeiden e.
LegionMammal978
2
Es ist sehr schwierig, ohne Englisch zu schreiben e , aber Gadsby tut es.
Akangka
Ich nehme keine quine Funktionen an?
Mama Fun Roll

Antworten:

24

CJam, 45 41 38 35 Bytes

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

Wenn das eingegebene Zeichen keines der Zeichen ist "$&)+,/:?HOX\_`el{}, druckt dieses Programm die folgende, leicht geänderte Version von sich. Probieren Sie es online!

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

Andernfalls druckt das Programm die folgende, verschleierte Version der Änderung. Probieren Sie es 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-~

Beachten Sie, dass einige der Zeichen nicht druckbar sind. Probieren Sie es online!

Wie es funktioniert

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

Im ersten möglichen Ausgabeprogramm vermeiden wir ~es, es im anderen Programm verwenden zu können. Daher _~endet das geänderte Programm statt mit OX$_?, was wie folgt funktioniert.

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

Schließlich im restlichen Ausgabeprogramm,

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

bricht alle diese Zeichen in ein Array ein und drückt daher die folgende Zeichenfolge.

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

If- subtrahiert 18 von jedem Zeichencode und drückt die Zeichenfolge

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

was ~die auswertet.

Dennis
quelle
18

JavaScript (ES6), 356 340 327 308 303 263

Verwenden Sie jetzt Function`...```für das zweite Programm:

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

Die Funktion packt sich in eines von drei möglichen Programmen:

  1. Das erste Programm ruft auf eval ein Zeichenfolgenliteral auf, das den Funktionscode enthält, wobei jedes Zeichen als Oktalwert maskiert wird.

    eval ('\ 146 \ 165 ...')
  2. Das zweite Programm leitet den Browser zu a weiter javascript: URL weiter, die den Funktionscode mit jeder Zeichen-URL enthält. Dies ist die einzige Möglichkeit, Code ohne Verwendung von Klammern auszuwerten. Es entgeht auch den Buchstaben in "eval".

    window ["\ x6coc \ x61tion"] ["hr \ x65f"] = "j \ x61 \ x76 \ x61script:% 66% 75 ..."
  3. Das letzte Programm ist schmerzhaft lang. Es baut den Code der Funktion auf, indem es einen hinzufügt (+9-8 ) erstellt, um jeden Zeichencode abzurufen. Dies dient dazu, die Verwendung von Oktalziffern zu vermeiden.

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

Das richtige Programm wird indiziert, indem eine sorgfältig erstellte Zeichenfolge nach dem eingegebenen Zeichen durchsucht wird:

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

Hier ist eine ungolfed, ungetestete Version. Möglicherweise funktioniert dies nicht, da die Quelle Zeilenumbrüche enthält.

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
quelle
function f(){ ... };f()kann sein (f=_=>{ ... })(). Hier ist ein Beispiel: es6fiddle.net/iiz2nq0l
Ismael Miguel
Noch besser: f=(_=prompt())=>...;f(). Die Eingabe wird gespeichert als _.
Mama Fun Roll
Außerdem wird console.log nicht benötigt, die Funktionsausgabe ist in Ordnung.
Mama Fun Roll
Verwenden Function`[code]`.call``;Sie keine Arbeit für Sie, anstatt umzuleiten? Hier ist ein funktionierendes Beispiel: es6fiddle.net/ij023v49 (Siehe? Nein evil()! Ähm, ich meine eval()...)
Ismael Miguel
Du hast heute etwas gelernt. Beachten Sie nur, dass das thisObjekt diese leere Vorlagenzeichenfolge sein wird. Es basiert auf dem FunctionKonstruktor, mit dem Sie eine Funktion erstellen können, anstatt sie auszuführen eval(). In der Funktion ist der Code im ersten Parameter enthalten. Ich benutze es eine Menge , um die reale zu bekommen window, mit Function('return this')(). Da Sie diese Funktion nicht verwenden können (), habe ich die Freundlichkeit von ES6 missbraucht, um zu versuchen, eine verwendbare Funktion auszuspucken, auf die Sie verzichten können() . Dazu benötigen Sie die .call()Methode, die die Funktion mit einem neuen thisObjekt aufruft .
Ismael Miguel