Lipogram „Quine”

26

Zadanie

  1. Weź jeden znak Unicode jako dane wejściowe.
  2. Wyprowadza program w tym samym języku, który również przestrzega tej specyfikacji, ale który nie zawiera znaku wejściowego.
  3. Jeśli twój program jest uruchamiany z wejściem a , a następnie program wyjściowy jest następnie uruchamiany z wejściem b , wówczas program, który wysyła, ZEZWALA zawierać znak a . Jednak b nadal nie może pojawiać się w tym programie. Innymi słowy, tylko wejście do najnowszej wersji programu jest zabronione.
  4. Niezależnie od tego, co może powiedzieć tytuł, obowiązują standardowe zasady quine.

Najkrótszy program wygrywa. Program musi mieć co najmniej jeden bajt.

Przykład

Jeśli programem jest ABCD. (# to komentarz)

> 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

Gdzie slangijest tłumacz dla fikcyjnego języka.

Akangka
źródło
Czy nie byłoby to wyzwanie mniej wyczerpującymi językami? Kilka używa słów w nazwach instrukcji, więc bardzo trudno i / lub niemożliwe jest unikanie znaków takich jak e.
LegionMammal978
2
Bez tego bardzo trudno jest pisać po angielsku e, ale Gadsby to robi.
Akangka
Zakładam, że nie ma żadnych funkcji quine?
Mama Fun Roll

Odpowiedzi:

24

CJam, 45 41 38 35 bajtów

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

Jeśli znak wejściowy nie jest żadnym ze znaków "$&)+,/:?HOX\_`el{}, program wypisuje następującą, nieco zmodyfikowaną wersję samego siebie. Wypróbuj online!

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

W przeciwnym razie program wydrukuje następującą, zaciemnioną wersję modyfikacji. Wypróbuj 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-~

Pamiętaj, że niektórych znaków nie można wydrukować. Wypróbuj online!

Jak to działa

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

W pierwszym możliwym programie wyjściowym unikamy używania go, ~aby móc go używać w innym programie. Dlatego zamiast _~zmodyfikowanego programu kończy się znak OX$_?, który działa w następujący sposób.

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

Wreszcie w pozostałym programie wyjściowym

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

opakowuje wszystkie znaki w tablicę, dlatego wypycha następujący ciąg.

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

If- odejmuje 18 od każdego kodu znakowego, popychając ciąg

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

który ~ocenia.

Dennis
źródło
18

JavaScript (ES6), 356 340 327 308 303 263

Teraz używa Function`...```do drugiego programu:

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

Funkcja pakuje się w jeden z trzech możliwych programów:

  1. Pierwszy program wywołuje evalliterał łańcuchowy zawierający kod funkcji, a każdy znak jest zastępowany wartością ósemkową.

    eval („\ 146 \ 165 ...”)
  2. Drugi program przekierowuje przeglądarkę na javascript:adres URL zawierający kod funkcji z zakodowanym adresem URL każdego znaku. To jedyny sposób, w jaki mógłbym ocenić kod bez użycia nawiasów. Unika także liter w „eval”.

    window ["\ x6coc \ x61tion"] ["hr \ x65f"] = "j \ x61 \ x76 \ x61script:% 66% 75 ..."
  3. Ostatni program jest boleśnie długi. Buduje kod funkcji, dodając po jednym ( +9-8), aby uzyskać kod każdego znaku. Ma to na celu uniknięcie używania cyfr ósemkowych.

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

Właściwy program jest indeksowany poprzez wyszukiwanie starannie skonstruowanego ciągu znaków wejściowych:

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

Oto niepoddana testom wersja. Może nie działać z powodu nowych linii w źródle.

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
źródło
function f(){ ... };f()może być (f=_=>{ ... })(). Oto przykład: es6fiddle.net/iiz2nq0l
Ismael Miguel
Nawet lepiej: f=(_=prompt())=>...;f(). Dane wejściowe są przechowywane jako _.
Mama Fun Roll
Ponadto nie ma potrzeby korzystania z pliku console.log, funkcja działa dobrze.
Mama Fun Roll
Nie będziesz używać Function`[code]`.call``;pracy zamiast przekierowywać? Oto działający przykład: es6fiddle.net/ij023v49 (Widzisz? Nie evil()! Erm, mam na myśli eval()...)
Ismael Miguel
Nauczyłeś się dzisiaj czegoś. Pamiętaj tylko, że thisobiektem będzie ten pusty ciąg szablonu. Zależy to od Functionkonstruktora, który umożliwia tworzenie funkcji zamiast uruchamiania eval(). Funkcja będzie miała kod zawarty w pierwszym parametrze. Używam go bardzo często, aby uzyskać prawdziwy window, przy użyciu Function('return this')(). Ponieważ nie możesz użyć (), nadużyłem trochę uprzejmości ES6, próbując wypluć użyteczną funkcję, bez której możesz uruchomić (). W tym celu potrzebujesz .call()metody, która wywołuje funkcję z nowym thisobiektem.
Ismael Miguel