Programma che si permette di codificare una stringa (quine-variante)


16

Scrivi un programma che stampa la seguente riga di 80 caratteri:

Questo programma da codegolf.stackexchange.com si consente di codificare una stringa.

accetta quindi una riga di input, quindi stampa il suo codice sorgente con i suoi punti di codice eventualmente riordinati (nessuno aggiunto e nessuno eliminato). Quando viene eseguito quel codice, deve accadere lo stesso, tranne che la riga stampata sarebbe la riga di input più recente.

La regex in stile Perl ^[A-Za-z0-9. ]{80}$corrisponderà a qualsiasi riga di input. Non è possibile fare ipotesi aggiuntive.

Il punteggio di un invio è il numero di punti di codice nel suo codice sorgente meno 94 . È meglio più basso.

Il codice non deve fare nulla di inaccettabile in un quine ( ad es. Lettura di file). In particolare, qualsiasi presentazione con un punteggio negativo deve in qualche modo barare, come 93! è inferiore a 64 80 .

Aggiunto il 21-04-2014: l'intero codice sorgente del programma deve essere ben formato nella codifica dei caratteri in base alla quale vengono conteggiati i punti del codice. Ad esempio, non è possibile utilizzare 80 byte consecutivi nell'intervallo di byte finali UTF-8 (80..BF) e contare ciascuno come un singolo CARATTERE DI SOSTITUZIONE U + FFFD (o peggio, poiché non è affatto un punto di codice).

Inoltre, se la codifica consente a più modi di codificare un punto di codice ( ad esempio SCSU ), il tuo programma, così come tutti i programmi che genera direttamente o indirettamente, deve utilizzarne solo uno (o almeno tutti devono essere trattati in modo equivalente in tutto il codice ).


Dopo aver riletto la tua domanda, non sono sicuro che la mia risposta faccia esattamente quello che avevi in ​​mente. Il piping della nuova stringa al programma è corretto o deve avviare un prompt interattivo?
Dennis,

@Dennis: non è per questo che la tua risposta non è accettabile. Piuttosto, legge l'input prima di stampare "Questo programma da [...]".
PleaseStand,

Questo è quello che volevo dire, non l'ho espresso bene. L'interprete GolfScript legge tutto ciò che viene reindirizzato prima di iniziare l'esecuzione dello script. L'unico modo per evitarlo è avviare un prompt, che rende impossibile il piping.
Dennis,

Ciao, ci sto provando in JavaScript. Sembra impossibile fare un quine senza leggere il testo tra i tag <script>? Qual è lo scopo di permutare il codice sorgente? Dici "eventualmente riordinato"; questo significa permutare solo se necessario?
bacchusbeale,

Risposte:


5

GolfScript, 231 162 131

'1àâ4ÿaVo5GùpZBtiXOürsóNîMmWåKHc09JdñúêyzíECäYïhDU ãáIFõ6é8òRìjTv23ønuðLwxfSkôbëAelqý.çèPQ
öûg7'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~

Come funziona

Iniziamo scegliendo 94 caratteri diversi che saranno autorizzati a codificare una stringa. 94 caratteri funzionerebbero, ma scegliamo quanto segue per scopi di golf:

\n .0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
àáâãäåçèéêëìíîïðñòóôõöøùúûüýÿ

Chiamiamo l'array di questi caratteri "&".

La riga di input conterrà sempre 81 caratteri (incluso LF). Tutti questi personaggi sono presenti nei primi 65 caratteri di “&”. Questo è l'unico motivo per scegliere i caratteri nei 128 byte superiori.

Sostituiamo ogni carattere della stringa con il suo indice in "&", quindi LF diventa 0, lo spazio diventa 1, ecc.

Consideriamo gli 81 numeri ottenuti le cifre di un singolo numero 65 di base. Chiamiamo questo numero "N".

Ora, enumeriamo tutte le possibili permutazioni di "&" e recuperiamo la permutazione corrispondente al numero dall'alto. Ciò si ottiene nel modo seguente:

  1. Imposta c = 1e A = [].
  2. Prepend N % cto A.
  3. Imposta N = N / ce c = c + 1.
  4. Se c < 95, torna a 2.
  5. Imposta i = 0e s = "".
  6. Recupera il carattere &[A[i]], aggiungilo a "s" e rimuovilo da "&".
  7. Set i = i + 1.
  8. Se i < 94torni a 6.

Supponiamo di avere blocchi di codice “E” e “D” che codificano e decodificano una stringa come spiegato sopra.

Ora, abbiamo bisogno di un wrapper per quei blocchi di codice che soddisfa i requisiti della domanda:

'encoded string'{\.$[{}/]:&; D puts '"#{`head -1`}"'~ E "'".@+\+\'.~'}.~

Questo fa quanto segue:

  • {…}.~definisce un blocco, lo duplica ed esegue la seconda copia. La prima copia rimarrà in pila.

  • \.$ scambia la stringa codificata con il blocco e crea una copia della stringa codificata, con caratteri ordinati.

  • [{}/]:&; converte la stringa dall'alto in un array, la salva in "&" e la scarta.

  • D puts decodifica la stringa codificata e stampa il risultato.

  • '"#{`head -1`}"'~legge una riga di input eseguendo head -1nella shell.

  • E "'".@+\+ codifica la stringa e antepone e accoda una singola citazione.

  • \'.~'scambia la stringa codificata e il blocco e accoda la stringa '.~'.

  • Dopo che il blocco è stato eseguito, GolfScript stampa il contenuto dello stack (stringa codificata, blocco, '.~') ed esce.

"E" può essere definito come segue:

{&?}%        # Replace each character by its index in “&”.
);           # Remove the last integer from the array, since it corresponds to the LF.
65base       # Convert the array to an integer “N” by considering it a base 65 number.
[            #
  94,        # For each integer “c” in 0 … 93:
  {          #
    )        # Increment “c”.
    1$1$%    # Push “N % c”.
    @@/      # Rotate “N % c” below “N” and “c” and divide the first by the latter.
  }/;        # Discard “N”.
]            # Collect the results of “N % c” in an array “A”.
-1%          # Reverse “A”.
&\           # Push “&” and swap it with “A”.
[            #
  {          # For each “j” in “A”:
    1$=.[]+  # Push “&[j] [&[j]]”.
    @^       # Rotate “&” on top of “[&[j]]” and take their symmetric difference.
  }/         #
]            # Collect the charcters into an array.

"D" può essere definito come segue:

0&           # Push 0 (initial value of the accumulator “A”) and “&”.
@            # Rotate the encoded string on top of “&”.
{            # For each character “c” of the encoded string:
    @2$,*    # Rotate “A” on top of the stack and multiply it by the length of “&”.
    2$2$?+   # Get the index of “c” in “&” and add it to “A”.
    @@^      # Rotate “A” below “&” and “c” and take their symmetric difference.
}/;          # Discard “&”.
65base       # Convert “A” into the array of its digits in base 65.
{&=}%        # Replace each digit by the corresponding character in “&”.
''+          # Convert the resulting array into a string.

Golf finale:

  • Sostituisci \.$[{}/]:&;0&@con 0@.$[{}/]:&\per salvare due caratteri.

  • Definire la funzione {;65base}:bper salvare un carattere.

  • Rimuovi tutto lo spazio tranne l'LF finale e l'LF nella stringa.

Esempio

$ # Create GolfScript file using base64 to avoid encoding issues.
$ base64 > permute.gs -d <<< JzHg4jT/YVZvNUf5cFpCdGlYT/xyc/NO7k1tV+VLSGMwOUpk8frqeXrtRUPkWe9oRFUg4+FJRvU26TjyUuxqVHYyM/hudfBMd3hmU2v0YutBZWxx/S7n6FBRCvb7ZzcnezBALiRbe30vXTomXHtAMiQsKjIkMiQ/K0BAXn0vezs2NWJhc2V9OmJ+eyY9fSUnJytwdXRzJyIje2BoZWFkIC0xYH0iJ357Jj99JSliWzk0LHspMSQxJCVAQC99LztdLTElJlxbezEkPS5AXn0vXSInIi5AK1wrXCcufid9Ln4K
$
$ # Set locale to en_US (or any other where one character is one byte).
$ LANG=en_US
$
$ # Go back and forth between two different strings.
$ # Second and sixth line are user input, not output from the script.
$
$ golfscript permute.gs | tee >(tail -n+2 > tmp.gs) && golfscript tmp.gs && rm tmp.gs
This program from codegolf.stackexchange.com permutes itself to encode a string.
Permuting source code code points to encode a string is a certain quine variant.
'18äJoS3sgV9qdçëxm0ÿKMNe5íPî.Htn2ciâIuøbRZéð4AwB7áìUüöôWõèûfñåLàóDrhQlO6
pTaýzòkùYCyFêïãG júEvX'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~
Permuting source code code points to encode a string is a certain quine variant.
This program from codegolf.stackexchange.com permutes itself to encode a string.
'1àâ4ÿaVo5GùpZBtiXOürsóNîMmWåKHc09JdñúêyzíECäYïhDU ãáIFõ6é8òRìjTv23ønuðLwxfSkôbëAelqý.çèPQ
öûg7'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~
$
$ # Sort all characters from the original source code and hash them.
$ fold -1 permute.gs | sort | md5sum
b5d978c81df5354fcda8662cf89a9784  -
$
$ # Sort all characters from the second output (modified source code) and hash them.
$ golfscript permute.gs | tail -n+2 | fold -1 | sort | md5sum
Permuting source code code points to encode a string is a certain quine variant.
b5d978c81df5354fcda8662cf89a9784  -
$
$ # The hashes match, so the characters of the modified source code are a permutation
$ # of the character of the original one.

224 meno 94 è 130.
mbomb007

Potresti elaborare?
Dennis,

1

Perl, 1428 1099

Questo ha 1193 caratteri ASCII (inclusi 960 cifre binarie permutate). 1193 - 94 = 1099

$s='010011100001100010101100111111101001101011101000100000101011011010100110111111011111101011101000100110111111011100101000011101011110100000101000100101011111111110101100101101011010011100100100011110110001011100100001011010100111100000011110111110011100101000100110111111101001011110101011100110101110101101011110101100111111100010101101101100011110100101011111111111101101101000111111011110100111011100101000011101011110111111011010111111101100101101101011100010100111100000111110';$_=q{$i=join'',A..Z,a..z,0..9,'. ';print map({substr$i,oct'0b'.$_,1}$s=~/.{6}/g),$/;chop($s=<>);$s=join'',map{sprintf"%06b",index$i,$_}$s=~/./g;$t=join'',map{$_ x(480-(()=$s=~/$_/g))}0,1;print"\$s='$s';\$_=q{$_};eval#$t"};eval#000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Il mio primo disegno

Prima di ricevere un suggerimento da Dennis per passare al binario, il mio programma permutava cifre ottali.

Il mio primo disegno codifica ogni stringa in 160 cifre ottali, con 2 cifre per carattere. Questa codifica ha 100 8 = 64 caratteri diversi. Il sistema ottale ha 8 cifre diverse. Il programma deve avere 160 copie di ogni cifra, quindi consente 8 × 160 = 1280 cifre.

Continuo a inserire 160 cifre $se le altre 1120 cifre $t. Comincio con un programma che non è un quine, ma stampa solo i compiti da $se $tper la corsa successiva. Questo è:

$s = '2341425477515350405332467737535046773450353640504537765455323444366134413247403676345046775136534656553654774255543645377755507736473450353677327754555342474076';
$t = '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777';

# $i = character map of 64 characters, such that:
#  substr($i, $_, 1) is the character at index $_
#  index($i, $_) is the index of character $_
$i = join '', 'A'..'Z', 'a'..'z', '0'..'9', '. ';

# Decode $s from octal, print.
#  1. ($s =~ /../g) splits $s into a list of pairs of octal digits.
#  2. map() takes each $_ from this list.
#  3. oct() converts $_ from an octal string to a number.
#  4. substr() on $i converts number to character.
#  5. print() outputs the characters from map() and a final "\n".
print map({ substr $i, oct, 1 } $s =~ /../g), "\n";

# Read new $s, encode to octal.
#  1. ($s = <>) reads a line.
#  2. chop($s) removes the last character of $s, the "\n".
#  3. ($s =~ /./g) splits $s into characters.
#  4. map() encodes each character $_ as a pair of octal digits.
#  5. join() concatenates the pairs from map().
chop($s = <>);
$s = join '', map { sprintf "%02o", index $i, $_ } $s =~ /./g;

# Make new $t.
#  1. map() takes each $_ from 0 to 7.
#  2. $_ x (160 - (() = $s =~ /$_/g)) makes a string where $_ repeats
#     160 times, minus the number of times that $_ appears in $s.
#  3. join() concatentates the strings from map().
$t = join '', map { $_ x (160 - (() = $s =~ /$_/g)) } 0..7;

# Print the new assignments for $s and $t.  This is not yet a quine,
# because it does not print the rest of the program.
print "\$s = '$s';\n\$t = '$t';\n";

(() = $s =~ /$_/g))è un'assegnazione a un elenco vuoto di variabili. Prendo questo trucco dal tutorial contestuale di PerlMonks . Forza il contesto dell'elenco sull'operatore di corrispondenza =~. In un contesto scalare, la corrispondenza sarebbe vera o falsa e avrei bisogno di un ciclo come $i++ while ($s =~ /$_/g)contare le corrispondenze. Nel contesto dell'elenco, $s =~ /$_/gè un elenco di corrispondenze. Ho inserito questo elenco nel contesto scalare di una sottrazione, quindi Perl conta gli elementi dell'elenco.

Per fare un quine, prendo il modulo $_=q{print"\$_=q{$_};eval"};evaldai quines Perl a Rosetta Code . Questo si assegna una stringa q{...}di $_e quindi chiama eval, così posso avere il mio codice in una stringa e anche eseguirlo. Il mio programma diventa un Quine quando mi avvolgo il mio terzo per ultime righe in $_=q{e };eval, e cambiare il mio ultimo printa print "\$s = '$s';\n\$t = '$t';\n\$_=q{$_};eval".

Infine, golf il mio programma cambiando il primo compito in $t in un commento e rimuovendo i caratteri extra.

Questo ha 1522 caratteri ASCII (inclusi 1280 cifre ottali permutate).
1522 - 94 = 1428

$s='2341425477515350405332467737535046773450353640504537765455323444366134413247403676345046775136534656553654774255543645377755507736473450353677327754555342474076';#0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
$_=q{$i=join'','A'..'Z','a'..'z','0'..'9','. ';print map({substr$i,oct,1}$s=~/../g),"\n";chop($s=<>);$s=join'',map{sprintf"%02o",index$i,$_}$s=~/./g;$t=join'',map{$_ x(160-(()=$s=~/$_/g))}0..7;print"\$s='$s';#$t\n\$_=q{$_};eval"};eval

Il passaggio al binario

Nei commenti, Dennis notò che 960 cifre binarie permutate sarebbero state inferiori a 1280 cifre ottali. Quindi ho rappresentato graficamente il numero di cifre permutate per ogni base da 2 a 16.

Maxima 5.29.1 http://maxima.sourceforge.net
using Lisp ECL 13.5.1
...
(%i36) n : floor(x);
(%o36)                             floor(x)
...
(%i41) plot2d(n * ceiling(log(64) / log(n)) * 80, [x, 2, 16],
              [xlabel, "base"], [ylabel, "number of permuted digits"]);
(%o41) 

grafico con base sull'asse x, numero di cifre consentite sull'asse y

Sebbene la base 8 sia un minimo locale, le basi 2 e 3 e 4 vincolano per la migliore base, a 960 cifre permutate. Per il golf del codice, la base 2 è la migliore perché Perl ha conversioni per la base 2.

Sostituendo 1280 cifre ottali con 960 cifre binarie si risparmiano 320 caratteri.

Il passaggio da codice ottale a binario costa 8 caratteri:

  • Cambiare octa oct'0b'.$_costi 7.
  • Modifica /../gai /.{6}/gcosti 2.
  • Modificare "%02o" in "% 06b" `costa 0.
  • Modifica 160ai 480costi 0.
  • Passa 0..7a 0,1Salva 1.

Ho imparato alcuni consigli sul golf Perl . Risparmiano 14 caratteri:

  • Passare 'A'..'Z','a'..'z','0'..'9'a A..Z,a..z,0..9, usando parole chiave e numeri nudi, salva 12 caratteri.
  • Passa "\n"a $/salva 2 caratteri.

Salvo 3 caratteri spostando il #$tcommento alla fine del file. Ciò rimuove la nuova riga che termina il commento e un valore letterale \nnel quine.

Queste modifiche salvano un totale di 329 caratteri e riducono il mio punteggio da 1428 a 1099.


1
L'uso di cifre binarie anziché ottali richiederebbe "solo" 960 caratteri permutabili.
Dennis,

@Dennis Grazie per la punta! Sono passato al binario (salvando 312 caratteri). Mentre ero qui, ho giocato a golf altri 17 personaggi.
kernigh,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.