Haskell , 3 quines, 1119 byte
Quine 1, 51 byte
Un'azione anonima IO
che stampa direttamente su stdout.
putStr`mappend`print`id`"putStr`mappend`print`id`"
Provalo online!
Quine 2, 265 byte
La funzione f
accetta un argomento fittizio e restituisce una stringa.
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,90,52,82,89,52,51,51,94,84,24,24,39,34,34,106,95,102,110,0,94,50,89,0,90,52,82,82,82,106,95,102,110,0,48,24,24,39,35,106,95,102,110,0,40,24,24,39,37,37,84,24,24,45,37,37,84,24,24,90,84,50,94,52]
Provalo online!
Quine 3, 803 byte
Tutto dopo il LANGUAGE
pragma è una funzione anyema che prende un argomento fittizio e restituisce una stringa.
{-#LANGUAGE CPP#-}(\q(_:_:_:_:_:_:_:_:z)y(#)_->(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z)'\''__TIME__(\(?)v k x->v$k?x)$ \(&)(%)v->v&'{'&'-'&'#'&'L'&'A'&'N'&'G'&'U'&'A'&'G'&'E'&' '&'C'&'P'&'P'&'#'&'-'&'}'&'('%'\\'&'q'&'('&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'_'&':'&'z'&')'&'y'&'('&'#'&')'&'_'&'-'&'>'&'('&'y'&'('%'\\'&'k'&' '&'x'&'-'&'>'%'\''&'&'%'\''&':'&'q'&':'&'k'&':'&'q'&':'&'x'&')'&'#'&'y'&'('%'\\'&'k'&' '&'x'&'-'&'>'%'\''&'%'%'\''&':'&'q'&':'%'\''%'\\'%'\\'%'\''&':'&'k'&':'&'q'&':'&'x'&')'&'$'&'y'&'('&':'&')'&'#'&'y'&'('&':'&')'&'$'&' '%'\\'&'x'&'-'&'>'&'x'&')'&'z'&')'%'\''%'\\'%'\''%'\''&'_'&'_'&'T'&'I'&'M'&'E'&'_'&'_'&'('%'\\'&'('&'?'&')'&'v'&' '&'k'&' '&'x'&'-'&'>'&'v'&'$'&'k'&'?'&'x'&')'&'$'&' '%'\\'&'('&'&'&')'&'('&'%'&')'&'v'&'-'&'>'&'v'
Provalo online!
Personaggi
Quine 1:
"S`adeimnprtu
Quine 2:
!+,.0123456789;<=[]bcfghosw
Quine 3:
#$%&'()-:>?ACEGILMNPTU\_kqvxyz{}
Come funziona
Quine 1
putStr`mappend`print`id`"putStr`mappend`print`id`"
Quine 1 è una versione modificata del mio recente Golf, una risposta quine (con miglioramenti di H.PWiz):
- Poiché non sono necessari programmi completi,
main=
è stato rimosso.
<>
e $
sono stati sostituiti dai loro quasi sinonimi mappend
e id
.
Questo libera i personaggi vitali =<>
e l'operatore utile $
per le altre quine.
Quine 2
f c=[b=<<g]!!0++show g;b c=[[[show 9!!0,show 1!!0..]!!6..]!!c];g=[93,0,......]
Quine 2 utilizza metodi in qualche modo simili per programmare 2 della mia recente risposta Quines reciprocamente esclusivi , ma adattati per restringersi direttamente e soprattutto per evitare di usare letterali di caratteri, necessari per Quine 3. Entrambi sono raggiunti con l'aiuto della show
funzione, che per pura fortuna non ha ancora usato nessuno dei suoi personaggi.
Questo quine utilizza le schede anziché gli spazi, ma ho usato gli spazi sottostanti per la leggibilità.
g
sono i dati di quine, come un elenco di numeri interi alla fine del codice. Ogni numero rappresenta un carattere dal resto del codice.
- I numeri vengono spostati di
9
, quindi quella scheda è 0
. Ciò rende la codifica un po 'più breve consentendo alle lettere minuscole per la funzione e ai nomi delle variabili di adattarsi a 2 cifre.
b c=[[[show 9!!0,show 1!!0..]!!6..]!!c]
è una funzione per convertire un numero in un carattere (in realtà una stringa di un carattere).
[[show 9!!0,show 1!!0..]!!6..]
è un intervallo di caratteri che inizia con un carattere di tabulazione, in cui è indicizzato !!c
.
- Il carattere di tabulazione si è prodotto indicizzando in un altro intervallo
[show 9!!0,show 1!!0..]
, inizia con i caratteri numerici '9'
e '1'
e saltare in incrementi di 8.
- I caratteri delle cifre vengono prodotti indicizzandoli nella
show
stringa della cifra corrispondente.
f c=[b=<<g]!!0++show g
è la funzione principale. c
è un argomento fittizio.
b=<<g
usa =<<
per convertire ogni numero nel g
suo carattere. (L'uso di =<<
piuttosto che ad es. map
È il motivo b
per cui deve racchiudere il suo carattere restituito in un elenco.)
show g
fornisce la rappresentazione in formato stringa g
dell'elenco e ++
concatena le stringhe.
- Poiché
=<<
ha una precedenza inferiore rispetto a ++
, è necessario un certo bracketing. Per evitare di usare ()
(riservato per quine 3), [...]!!0
indicizza in un elenco con un elemento.
Quine 3
In base alla progettazione degli altri quines, quine 3 ha ancora accesso a parentesi, espressioni lambda, valori letterali dei caratteri e al costruttore stringa / elenco :
. Questo sarà sufficiente per costruire una funzione che antepone il codice del quine a una stringa.
Sfortunatamente, y
sono state usate tutte le vocali minuscole (tranne qualche volta ), senza lasciare utili funzioni incorporate alfanumeriche. Inoltre se ne []""
sono andati. Questo non lascia un modo normale per costruire una stringa vuota per iniziare a fingere il codice.
Tuttavia, quasi tutte le lettere maiuscole sono ancora disponibili, quindi è possibile un LANGUAGE
pragma per ottenere un'estensione della lingua. Ancora una volta, per pura fortuna, CPP
(abilita il preprocessore C) è l'unica estensione del linguaggio chiamata con solo lettere maiuscole. E le macro CPP hanno spesso nomi in maiuscolo.
Quindi, per ottenere la stringa vuota essenziale, il quine abilita CPP
, usa la __TIME__
macro per ottenere una costante di stringa del modulo "??:??:??"
(convenientemente garantito per avere sempre la stessa lunghezza), e corrispondenze di pattern su di essa.
{-#LANGUAGE CPP#-}(\q(_:_:_:_:_:_:_:_:z)y(#)_->(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z)'\''__TIME__(\(?)v k x->v$k?x)$ \(&)(%)v->v&'{'&'-'&......
Dopo il pragma del linguaggio, il quine è costituito da un'espressione lambda che lega i suoi parametri a questi quattro argomenti (lasciando un parametro fittizio finale _
da applicare in seguito):
q
vincolato a '\''
, dando un singolo carattere di citazione;
_:_:_:_:_:_:_:_:z
legato a __TIME__
, come una stringa simile "??:??:??"
, creando così z
una stringa vuota;
y
associato a (\(?)v k x->v$k?x)
, un combinatore lambda utilizzato per aiutare a convertire i dati di quine dal modulo associato a sinistra ("foldl") in associato a destra ("foldr");
- L'operatore è
(#)
legato a \(&)(%)v->v&'{'&'-'&...
, i dati di quine stessi.
I dati di Quine sono forniti in una forma di codifica Church, un'espressione lambda con parametri (&)(%)v
.
- Applicando l'espressione di determinati valori per istanziare
(&)
, (%)
e v
, questa codifica può essere utilizzato per costruire il codice di base del quine o ricostruire la rappresentazione dei dati quine stessa.
- Secondo la regola di fissità predefinita di Haskell,
&
e %
diventa operatori associativi di sinistra all'interno della lambda. In questo modo i parametri dei caratteri si combinano con l' v
inizio iniziale da sinistra.
- Per la maggior parte dei personaggi
k
, esiste un corrispondente &'k'
.
- Quando
k
è '
o \
, che deve essere evaso all'interno dei letterali dei caratteri, la codifica è invece %'\k'
.
Poiché la codifica dei dati è associativa sinistra, ma le stringhe sono costruite in modo associativo destro, il combinatore y = (\(?)v k x->v$k?x)
viene introdotto per colmare la mancata corrispondenza.
y(...)
è destinato a costruire funzioni adatte per l'utilizzo come dati (&)
e (%)
operatori di Quine .
v
è una funzione da stringhe a stringhe (i dati di quine data v
sono esempi).
k
è un carattere, x
una stringa e ?
un operatore che li combina in una nuova stringa. (Per il codice principale (?)=(:)
,. Per ricostruire effettivamente la rappresentazione dei dati quine, è più complicato.)
- Quindi
y(?)v k = \x->v$k?x
è un'altra funzione dalle stringhe alle stringhe.
Come esempio di come questo cambi associatività, se (&)=y(:)
:
(v&k1&k2&k3) x
= (((v&k1)&k2)&k3) x
= y(:)(y(:)(y(:)v k1)k2)k3 x
= y(:)(y(:)v k1)k2 (k3:x)
= y(:)v k1 (k2:(k3:x))
= v (k1:(k2:(k3:x)))
= v (k1:k2:k3:x)
Più in generale, quando (#)
è la funzione di dati quine e f1,f2
sono funzioni che combinano caratteri con stringhe:
(y(f1)#y(f2)$v) x
= (...(y(f1)(y(f1)v '{') '-')...) x
= v(f1 '{' (f1 '-' (... x)))
applicando la funzione di dati di Quine con (&)=y(f1)
e (%)=y(f2)
, e questo utilizza il valore prescritto f1
e f2
per combinare i caratteri di dati di Quine con x
, quindi passa la stringa risultante a v
.
Il corpo della principale espressione lambda mette tutto insieme:
(y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x)$y(:)#y(:)$ \x->x)z
'&':q:k:q:x
per un carattere k
antepone &'k'
alla stringa x
, mentre '%':q:'\\':k:q:x
antepone %'\k'
, che sono i loro moduli di dati quine originali.
- Quindi
y(\k x->'&':q:k:q:x)#y(\k x->'%':q:'\\':k:q:x
sono i parametri giusti per ricostruire la rappresentazione dei dati Quine, anteposti alla finale z
(la stringa vuota) e quindi passati alla seguente funzione.
y(:)#y(:)
sono i parametri giusti per anteporre il codice core del quine a una stringa, senza altre modifiche.
- Alla fine non
\x->x
arriva a fare nulla con il quine costruito, che viene restituito.