Generatore di quine generalizzato


19

La sfida

In questa sfida, si specifica una lingua di origine S e una lingua di destinazione T . Il tuo compito è scrivere il seguente programma Pnella lingua S. Se viene fornito un programma valido Qnella lingua Tcome input per P, verrà generato un programma valido Rnella lingua Tche non accetta input e output Q(R), ovvero il programma Qapplicato al codice sorgente di R. Inoltre , dovresti presentare nella tua risposta un programma di esempio non banale Q(più interessante, meglio è, anche se non ottieni punti per questo), il programma risultante Re l'output di R. Questo è code-golf, quindi il codice più breve per le Pvittorie.

In altre parole, questa è una sfida nello scrivere un "costruttore universale di quine" in grado di creare tipi arbitrari di quine generalizzate.

chiarimenti

  • Le lingue di origine e di destinazione potrebbero essere identiche.
  • Il programma Pdovrebbe prendere una stringa come input (da STDIN o equivalente) e produrre una stringa (a STDOUT o equivalente), come ogni programma di output R.
  • I programmi di input Qdovrebbero anche trasformare una stringa in un'altra stringa, ma la loro forma è più flessibile: possono essere funzioni da stringa a stringa, frammenti di codice che modificano una variabile con un determinato nome, frammenti che modificano lo stack di dati se la lingua di destinazione ne ha uno, ecc. È inoltre possibile limitare ulteriormente la forma degli elementi Qdichiarando che, ad esempio, non possono contenere commenti. Tuttavia, devi essere in grado di implementare qualsiasi funzione calcolabile da stringa a stringa come programma di input Qe devi dichiarare esplicitamente come funzionano e quali ulteriori vincoli vengono posti su di essi.
  • Il programma di output Rdovrebbe davvero essere un quine (generalizzato), quindi non deve leggere alcun input (input dell'utente, file ecc.) A meno che Qnon lo faccia.
  • Le scappatoie standard non sono ammesse.

Un esempio

Supponiamo che io scelga Python come lingua di origine e Haskell come lingua di destinazione e che richieda inoltre che il programma di input sia una definizione di una riga di una String -> Stringfunzione denominata f. Se do il programma di inversione di stringa

f x = reverse x

come input per il mio programma Python P, genererà il codice sorgente di un altro programma Haskell R. Questo programma stampa su STDOUT il codice sorgente di R, ma invertito. Se Pviene assegnata la funzione identità

f x = x

come input, il programma di output Rè un quine.

Risposte:


7

Sorgente = Target = CJam, 19 17 16 byte

{`"_~"+}`)q\"_~"

Ciò presuppone che il programma di input Q(dato su STDIN) sia un frammento di CJam che prevede una stringa in cima allo stack e lascia un'altra stringa in cima allo stack.

Provalo qui.

Esempi

  1. L'identità sarebbe solo uno snippet vuoto, quindi lasciare STDIN stampe vuote

    {`"_~"+}_~
    

    Qual è il quine standard, con un ulteriore +.

  2. Per invertire una stringa in CJam, è possibile utilizzare W%, quindi inserendo STDIN, si ottiene:

    {`"_~"+W%}_~
    

    che possiamo eseguire per ottenere

    ~_}%W+"~_"`{
    
  3. Come terzo esempio, diciamo che utilizziamo un frammento, che alterna una stringa con spazi: ' *. Correndo Pcon quello come input, otteniamo

    {`"_~"+' *}_~
    

    che a sua volta stampa

    { ` " _ ~ " + '   * } _ ~  
    
  4. Ora funziona anche se Qcontiene interruzioni di riga (anche se non è mai necessario in CJam). Ecco un programma con un'interruzione di riga, che rimuove tutte le interruzioni di riga da una stringa (in modo inutilmente contorto - dividere in righe, quindi unire):

    N/
    ""
    *
    

    Ciò si traduce in quanto segue R:

    {`"_~"+N/
    ""
    *}_~
    

    che a sua volta stampa

    {`"_~"+N/""*}_~
    

Spiegazione

Diamo un'occhiata prima all'output prodotto:

Lo standard CJam Quine è

{`"_~"}_~

Funziona come segue:

  • Spingi il blocco {`"_~"}.
  • Duplicalo con _.
  • Eseguire la copia con ~.
  • Ora all'interno del blocco, `trasforma il primo blocco nella sua rappresentazione di stringa.
  • "_~" spinge i due caratteri della sorgente che non fanno parte del blocco (e quindi mancano dalla rappresentazione della stringa).
  • Le due stringhe sono stampate schiena contro schiena alla fine del programma.

Nel quine di base `non è necessario, perché se lasci il blocco così com'è, viene stampato lo stesso alla fine del programma.

L'output del mio programma Pè una versione modificata di questo frammento. Innanzitutto, ho aggiunto +a al blocco, che concatena le due stringhe in una stringa contenente l'intero sorgente. Nota che questo sarà vero indipendentemente da ciò che faccio all'interno del blocco, perché tutto ciò verrà aggiunto alla rappresentazione della stringa ottenuta con `. Ora posso semplicemente inserire il programma / frammento Qall'interno del blocco dopo il +, in modo che possa modificare la stringa di origine prima che venga stampata. Ancora una volta, poiché Qva all'interno del blocco, farà parte di detta stringa sorgente.

In sintesi, Pstampe

{`"_~"+Q}_~

Ora, per come sto andando a costruire questo output in P:

{`"_~"+}         "Push the block without Q.";
        `        "Turn it into a string. This is shorter than writing a string right away,
                  because I'd have to escape the quotes, and I'd need two quotes instead of
                  one backtick.";
         )       "Pop off the last character (the brace) and push it on the stack.";
          q      "Read input Q.";
           \     "Swap Q with the brace.";
            "_~" "Push the final two characters.";

Le quattro stringhe vengono stampate automaticamente (back-to-back) alla fine del programma.


1
Bene, questo è stato veloce! E sicuramente difficile da battere. Anche la spiegazione è buona.
Zgarb,

Dove hai appreso che W% inverte? dl.dropboxusercontent.com/u/15495351/cjam.pdf non ce l'ha
Faraz Masroor

Esiste un elenco più completo di metodi?
Faraz Masroor,

@FarazMasroor sourceforge.net/p/cjam/wiki/Basic%20operators/#percent (n. 3) ... è una funzionalità presa in prestito da GolfScript e ad un certo punto qualcuno mi ha detto che funziona in GolfScript. Sembra un idioma così comune che è una strana conoscenza implicita che ogni utente di CJam / GS ha ma che in realtà non è spiegata in molti posti. (Per ulteriori operatori non completamente documentati, consultare sourceforge.net/p/cjam/wiki/Operators )
Martin Ender

3

Espressioni di Haskell → Espressioni di Haskell, 41 byte

((++)<*>show).('(':).(++")$(++)<*>show$")

Provalo online!

Come funziona

P $ "Q"= ((++)<*>show).('(':).(++")$(++)<*>show$") $ "Q"costruisce "R"da

  1. (++")$(++)<*>show$"): aggiunta della stringa ")$(++)<*>show$",
  2. ('(':): anteporre il personaggio '('e
  3. (++)<*>show(= \x->x++show x): aggiungendo una versione quotata di quella,

risultante in "R"= "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\"".

R= (Q)$(++)<*>show$"(Q)$(++)<*>show$"funziona di

  1. prendendo la corda "(Q)$(++)<*>show$",
  2. (++)<*>show: aggiungendo una versione quotata di quella,
  3. applicando Qa quello,

risultante in Q "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\""= Q "R".

(I genitori in giro Qsono necessari perché Qpotrebbero contenere $altrettanto facilmente R, ed $è purtroppo associativo.)

dimostrazione

λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "id"
(id)$(++)<*>show$"(id)$(++)<*>show$"
λ> putStrLn $ (id)$(++)<*>show$"(id)$(++)<*>show$"
(id)$(++)<*>show$"(id)$(++)<*>show$"
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "reverse"
(reverse)$(++)<*>show$"(reverse)$(++)<*>show$"
λ> putStrLn $ (reverse)$(++)<*>show$"(reverse)$(++)<*>show$"
"$wohs>*<)++($)esrever("$wohs>*<)++($)esrever(
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "length"
(length)$(++)<*>show$"(length)$(++)<*>show$"
λ> print $ (length)$(++)<*>show$"(length)$(++)<*>show$"
44

Non solo $ha bisogno delle parentesi, ma anche finale let, doo le espressioni lambda.
Ørjan Johansen,

@ ØrjanJohansen Giusto, ma avrei potuto definire un sottoinsieme di lingue che non consente lambda non verniciata / let/ if/ case/ dose non li emetto da solo. Forse è altrettanto bene che non dovevo farlo.
Anders Kaseorg,

2

Sorgente = Target = JavaScript, 66

console.log("function a(){console.log("+prompt()+"(a+'a()'))}a()")

Ipotesi per Q:

  • Q dovrebbe essere una funzione anonima JavaScript da stringa a stringa.

Esempi:

  • Indietro . Q =function(s) { return s.split('').reverse().join(''); }

In questo caso, P(Q)(o R) sarà:, function a(){console.log(function(s) { return s.split('').reverse().join(''); }(a+'a()'))}a()ed eseguendolo, otterremo: )(a}))')(a'+a(} ;)''(nioj.)(esrever.)''(tilps.s nruter { )s(noitcnuf(gol.elosnoc{)(a noitcnufche è esattamente lo stesso di Q(R).

  • Identità . Q =function(s) { return s; }

in questo caso, P(Q)(o R) sarà: function a(){console.log(function(s) { return s; }(a+'a()'))}a()che è un JavaScript Quine . Inutile dire Q(R)che sarà lo stesso, poiché Q è la funzione Identità.


Alcune note:

STDIN in JavaScript è tradizionalmente prompt(), tuttavia, mi sono permesso di astenermi dalla tradizione di alert()STDOUT, al fine di rendere più semplice il processo di esecuzione dell'output come programma usando copia-incolla. (Mi rendo conto di poter salvare fino a 12 caratteri quando cambio a alert()).

Posso anche rendere le cose molto più brevi in ​​ES6, ma per ora voglio rimanere con JavaScript nativo. Sto pensando di presentare una risposta S = Scala, T = ECMA6 in futuro, solo per l'esperienza.

Capisco anche che JavaScript non può quasi mai battere CJam nel , ma ho dovuto affrontare questa sfida! Era sicuramente divertente.


Grazie! Sarebbe davvero bello avere una voce con diverse lingue di origine e di destinazione.
Zgarb,

2

Gelatina7 , 9 byte

“ṚƓ^ṾṂ’³3

Provalo online!

Q è una funzione 7 (ovvero che non guarda oltre l'elemento dello stack superiore e fa I / O tramite lo stack) e viene fornita come argomento da riga di comando.

Spiegazione

Il programma 7

Il costruttore universale di Quine in 7 che uso qui è:

717162234430…3

La prima cosa da notare è che il 7 principale è l'equivalente dello spazio bianco principale e non ha alcun effetto sul programma. L'unico motivo per cui è lì è obbedire alle regole di PPCG contro i quines solo letterali (è codificato dal secondo 1nel programma piuttosto che da se stesso).

Il resto del programma è un singolo elemento dello stack (ha 7s e 6s bilanciati ), che esegue quanto segue quando eseguito:

717162234430…3
 1716           Push a stack element "7" onto the stack
     2          Copy it
      23        Pop and output one of the copies (selecting format 7)
        4430    Prepend it to the top of stack
             3  Output it

In altre parole, questo elemento dello stack è un programma che stampa la parte superiore dello stack, con 7 anteposto, nel formato di output 7 (che significa "stampa letteralmente, usando la stessa codifica del codice sorgente", e quindi è chiaramente la migliore codifica per quines). È abbastanza fortunato qui che possiamo riutilizzare il valore letterale 7per due scopi (il formato di output e lo spazio bianco principale). Chiaramente, inserendo qualcosa appena prima del finale 3, possiamo produrre una funzione di 7+ input, anziché semplicemente emettere 7e il inserire direttamente.

In che modo questo elemento stack arriva al suo codice sorgente? Bene, quando viene raggiunta la fine del programma, 7eval s l'elemento stack superiore per impostazione predefinita. Tuttavia, in realtà non viene estratto dallo stack nel processo, quindi l'elemento stack letterale che è stato evalportato è ancora lì. (In altre parole, il programma non sta leggendo la propria fonte - come dimostra il fatto che non è in grado di vedere 7all'inizio del programma, che è un separatore di elementi dello stack piuttosto che parte di un letterale - ma piuttosto consiste principalmente in un letterale che viene evalguidato di default.)

Il programma Jelly

Questo è forse uno dei programmi Jelly meno simili a quelli che ho scritto; essa consiste di tre nilads ( “ṚƓ^ṾṂ’, ³, non come una serie di comandi, o anche come un numero ottale (simile concettualmente è), ma come numero decimale, il che significa che non occorre alcuna speciale formattazione per l'uscita. Tale decimale il numero diventa nella notazione intera compressa di Jelly.3 ), che sono appena uscita in sequenza perché non si effettuano operazioni su di essi. È 3abbastanza ovvio, essendo solo una costante intera. Il ³è anche semplice se si sa Jelly: è la notazione esplicita di gelatina per il primo argomento della riga di comando (che è dove Jelly richiede in genere il suo input). Il resto del programma Jelly rappresenta la maggior parte del mio 7 costruttore di quine universale: sfruttando il fatto che tutti i comandi in 7 possono essere rappresentati usando le cifre ASCII, possiamo interpretare717162234430“ṚƓ^ṾṂ’

Esempio

Se diamo 24053come programma Q, otterremo il seguente output:

717162234430240533

Provalo online!

2405 concatena l'elemento stack superiore a se stesso:

2405   Stack   Explanation
       x
2      x|x     Duplicate top of stack
 4     x||x    Swap two stack elements, with an empty element between
  0    x|(X)   Escape the top stack element, then concatenate the top two
   5   xx      Execute the top stack element

(L'ultimo passaggio potrebbe sembrare un po 'confuso; ciò che sta accadendo è che l'escape di un elemento dello stack converte ogni comando in esso da "esegui questo comando" a "aggiungi questo comando in cima allo stack", quindi ogni comando si aggiunge all'originale elemento stack superiore mentre viene eseguito.)

Pertanto, l'esecuzione del programma risultante R ci dà due copie di R:

7171622344302405371716223443024053

2

CJam → CJam, 13 byte

{`"_~"+7}_~qt

Provalo online!

L'input Qdeve essere uno snippet di codice che modifica l'unica stringa nello stack. Qviene letto dallo stdin.

Esempio

Ingresso:

S*W%

Aggiunge uno spazio tra ogni due caratteri e inverte la stringa.

Produzione:

{`"_~"+S*W%}_~

Uscita del quinto generalizzato:

~ _ } % W * S + " ~ _ " ` {

Spiegazione

{`"_~"+7}_~      e# Evaluate a generalized quine in CJam that only appends a 7.
q                e# Read the input.
t                e# Replace the 7th character (0-based) with the input.

Innanzitutto valuta il quine, quindi possiamo ottenere la sua rappresentazione di stringa senza virgolette doppie non necessarie. Quindi sostituire il payload con l'input.

Potrebbe essere {`"_~"+ }_~7qtdove lo spazio è il segnaposto del payload. Ma cambiando il payload per 7salvare un byte.


1

CarbonePerl (5), 29 33 byte

A$_=q(αA);evalβαS"\α$_β\n";printβ

Provalo online!

Il programma Perl Q dovrebbe restituire uno snippet che prende input come stringa sul lato destro e fornisce output nella variabile $_. (Le funzioni arbitrarie di Perl possono essere convertite in questo modulo avvolgendole come sub x {…}; $_=x. Nella maggior parte dei casi, tuttavia, la sintassi di Perl significa che non è necessario alcun wrapping.)

Spiegazione

Il Perl

Ecco come appare il costruttore universale Perl quine:

$_=q(…"\$_=q($_);eval";print);eval

(Nella maggior parte dei casi si vorrebbe giocare a golf fino a questo $_=q(say…"\$_=q($_);eval");eval, ma non sono sicuro che si possa adattare il codice Perl arbitrario lì.)

In altre parole, abbiamo un wrapper esterno $_=q(…);evalche assegna una stringa $_e quindi la valuta. All'interno del wrapper c'è "\$_=q($_);eval", cioè una ricostruzione del wrapper insieme al suo contenuto tramite l'utilizzo del valore in cui siamo memorizzati $_, più il codice Q specificato dall'utente, oltre printa stampare l'output. (Purtroppo non possiamo usarlo say; aggiunge una nuova riga e questo è rilevante nei quines.)

Il carbone

Il "punto" di questa risposta era produrre quine generalizzate in Perl, quindi una volta ho avuto una strategia golfistica per farlo (una che ho usato in molte altre risposte), era tempo di scrivere il programma P, che in sostanza sostituisce una stringa in un modello. Quello che volevo qui era un linguaggio che fosse bravo a stampare stringhe costanti (idealmente comprimendole un po ') e ad interpolare l'input dell'utente in esse.

Dopo averne provato alcuni, ho optato per Charcoal, che non avevo mai usato prima (e che potrebbe davvero fare con un po 'di documentazione); è progettato per l'arte ASCII ma è in grado di scrivere stringhe anche in una dimensione. I caratteri ASCII sono stampati letteralmente in carboncino, il che significa che la stampa di stringhe costanti non richiede alcuna piastra di caldaia e possiamo usare il comando per interpolare una stringa presa dall'input dell'utente nel programma.

È possibile andare (leggermente) più corto, però. Il costruttore di Quine universale Perl contiene due sezioni ripetute abbastanza lunghe. Possiamo quindi usare il comando per assegnarli alle variabili (ad es. A…αAssegna alla variabile α) e semplicemente interpolare le variabili nella stringa che stiamo stampando usando i loro nomi. Ciò consente di risparmiare pochi byte semplicemente scrivendo la stringa letteralmente.

Sfortunatamente, Charcoal aggiunge anche una nuova riga al programma, ma non è un grosso problema; costa semplicemente due byte per \naggiungere anche quella newline all'input di Q.

Esempio

Se diamo l'input $_=reverse(che inverte una stringa), otteniamo il seguente output:

$_=q($_=reverse"\$_=q($_);eval\n";print);eval

Provalo online!

che è un po 'simile che stampa la sua fonte all'indietro, come previsto.


1

GelatinaSottocarico , 15 byte

“(a(:^)*“S):^”j

Provalo online!

Accetta la funzione Underload Q di input come argomento simile a un comando. Q deve prendere input dallo stack e spingere l'output nello stack, senza tentare di ispezionare gli elementi dello stack più profondi (poiché non esistono).

Spiegazione

The Underload

Il costruttore di quine universale Underload utilizzato qui è:

(a(:^)*…S):^

Gran parte del programma è un singolo letterale. Lo seguiamo da :^, che lo copia, quindi valuta una copia (lasciando l'altra copia in pila).

Quando il valore letterale inizia a valutare, eseguiamo a(escape, che lo riporta nella stessa forma del programma originale A), e (:^)*(che aggiunge :^), ricostruendo così l'intero codice sorgente del programma. Possiamo quindi eseguire la funzione Q per trasformarla in modo arbitrario e stampare il risultato con S.

The Jelly

Questa volta non riesco a utilizzare Charcoal perché un interprete Underload di convalida si arresta in modo anomalo alla fine del programma se il programma termina con una nuova riga. (Alcuni interpreti di Underload, come quello su TIO, non applicano questa regola, ma volevo essere adeguatamente trasportabile.) Sfortunatamente, Charcoal aggiunge naturalmente nuove righe finali al suo output. Invece, ho usato Jelly, che è quasi altrettanto concisa in casi semplici come questo; il programma è costituito da un elenco letterale con due elementi ( ““”) e li unisce all'input ( j), interpolando così l'input dell'utente nel programma.

Esempio

Usando l'input :S^(stampa una copia, quindi valuta l'originale), otteniamo il seguente programma Underload:

(a(:^)*:S^S):^

Provalo online!

Questo si stampa all'infinito molte volte, in un modo abbastanza interessante: dopo aver fatto il normale comportamento di quine, viene eseguito evalsu una copia di ciò che emette. Ciò fa sì che l'intero programma ricostruito venga eseguito di nuovo indefinitamente (Underload è ricorsivo della coda). Citare te stesso e fare un evalè in realtà l'unico modo per fare un ciclo infinito in Underload.


Il carbone non aggiunge più nuove righe finali (yay)
solo ASCII il

1

RProgN 2 , 11 byte

'{`{.%s}{'F

Spiegazione del programma

'{`{.%s}{'F
'{`{.%s}{'  # Push the string "{`{.%s}{" to the stack.
          F # Format the input with the top of the stack as a template. Which produces {`{.<INPUT>}{

Chiarimento

Il quine che viene prodotto è semplice, ma utilizza la funzionalità di gestori di funzioni senza eguali in RProgN2 per creare un quine breve e dolce, chiamato quine "Loop". È un concetto sorprendentemente simile a un <> <quine.

{`{.}{
{`{.}   # Push the function {`{.} to the stack.
     {  # Try to define a new function, fail, loop back to index 1. (Which in turn, skips the function definition.)
 `{     # Push the string "{" to the stack.
   .    # Concatenate the top two values of the stack, which stringifies the function, then appends { to it.
    }   # Try to terminate a function, fail quietly, and terminate the program.

Ovviamente, a causa della struttura di questo quine, qualsiasi cosa tranne il vero no-ops (che non viene stringito) può essere posizionata dopo la funzione concatenata, e

Alcuni quines

  • {`{.i}{: Uscite {}i.{`{. iè solo la funzione "inversa", quindi questo programma si emette invertito.
  • {`{.S§.}{: Uscite ..S`{{{}§. Sconverte la stringa in una pila di caratteri, §ordina la pila lessicograficamente, quindi la .unisce di nuovo, risultando ordinata.

Provalo online!

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.