Markov Chain Quine

17

Se utilizará un modelo de Markov simple en esta pregunta. Para obtener más información sobre las cadenas de Markov, consulte http://setosa.io/ev/markov-chains/ .

Toma una cuerda. Para este ejemplo, usaremos la palabra:

reader

Ahora, para cada carácter, tome los caracteres que aparecen después de cada aparición del carácter en la cadena. ( ​`^`​representa el inicio de la cadena y ​`$`​representa el final)

`^` -> {'r'}       # After the start of the string, there is an `r`.
'r' -> {'e', `$`}  # After the first `r` (*r*eader), there is an `e`
                   # after the second (reade*r*), there is the end of the string.
'e' -> {'a', 'r'}
'a' -> {'d'}
'd' -> {'e'}

Ahora, comenzando desde el comienzo de la cadena, elija aleatoriamente uno de los personajes del siguiente conjunto. Agregue este personaje y luego elija entre los personajes en su próximo conjunto, y así sucesivamente hasta llegar al final. Aquí hay algunas palabras de ejemplo:

r
rereader
rer
readereader

Si un personaje aparece después de otro personaje varias veces, es más probable que sea elegido. Por ejemplo, en cocoa can, después de un c, hay dos tercios de posibilidades de obtener un oy un tercio de posibilidades de obtener un a.

'c' -> {'o', 'o', 'a'}

Desafío

Cree un programa que no tome entrada y genere una cadena aleatoria generada usando una Cadena de Markov, como arriba, donde la entrada a la cadena es la fuente del programa.

  1. El programa debe tener al menos dos caracteres, dos de los cuales deben ser iguales (para evitar cadenas "aburridas" que solo tienen una salida)
  2. Puede modificar el modelo para usar bytes en lugar de caracteres si lo desea, pero cambie "caracteres" a "bytes" en la regla 1
  3. El programa debería generar cadenas al azar con la frecuencia esperada en teoría

Este es el , por lo que gana el programa más corto.

Artyer
fuente
@ mbomb007 toda la información está en la pregunta, el enlace es solo extra si te interesa (Esta es una implementación muy básica)
Artyer
3
¿Por qué están los ^y $entre comillas? puede que sea más claro eliminarlo de las comillas o ponerlas entre comillas.
Destructible Lemon

Respuestas:

6

Pip , 64 bytes

Esto fue divertido.

t:V Y\"m:"Yt@0T9=A OyY@>RC(t(Xy).'.)"ST["t:V Y"RPy";Vm"C9]\";Vm<tab>

<tab>representa un carácter de tabulación literal ( 0x09). Pruébalo en línea!

¿Cómo?

TL; DR: sintaxis de cadenas de escape, repr y eval.

Para las cadenas que necesitan contener "caracteres literales , Pip ha escapado de cadenas , utilizando \"como delimitador. Una quine estándar que usa cadenas escapadas se vería así:

V Y\""V Y".RPy\"

Es decir: Yank (almacenando como y) una cadena que contiene "V Y".RPyy e Val. RPytoma la repr de y, a la que anteponemos la cadena literal V Y. Finalmente, muestre el resultado de la evaluación.

La estructura de la línea de Markov es similar, excepto que queremos guardar el código en lugar de generarlo y luego hacer algunas cosas con él. t:V Y\"...\"asigna el resultado eval a t. Dentro del código evaluado, m:"..."asigna una cadena de código a la mcual evaluaremos al final Vm.

ST["t:V Y"RPy";Vm"C9] construye una lista que contiene

"t:V Y"  Literal string
RPy      Repr(y)
";Vm"    Literal string
C9       Tab character

y lo convierte en una cadena, que por defecto concatena todos los elementos. Esta sección es equivalente a "V Y".RPyla quine original. Como es la última expresión en la cadena de evaluación grande, su valor es lo Vque devuelve el operador y, por lo tanto, lo que se le asigna t.

Por lo tanto, después de la evaluación y la asignación, tes igual al código completo y mcontiene

Yt@0T9=A OyY@>RC(t(Xy).'.)

Ahora Vmevalúa eso como código. Analicemos lo que sucede.

                            We'll use y to hold the current character in the chain
Yt@0                        Yank first character of t into y (chain always starts there)
         Oy                 Output y without newline each time we...
    T9=A                    Loop till ASCII code of y equals 9 (tab)
                            Since there's only one literal tab, at the end of the program,
                              this satisfies the Markov chain ending requirement
                   Xy       Generate a regex that matches y
                  (  ).'.   Concatenate . to regex: now matches y followed by any character
                (t       )  Find all matches in t (returns a list)
              RC            Random choice from that list
           Y@>              Slice off the first character and yank the remaining one into y

Un par de notas:

  • Terminar el código con una pestaña literal fue más corto que hacer una prueba de expresión regular para el "siguiente carácter o final de la cadena".
  • La expresión regular que utilicé no funciona correctamente si hay caracteres duplicados en el código; por ejemplo, aplicarlo xxysolo devolvería xxy no xyen los partidos. Afortunadamente, sin embargo, no hay caracteres duplicados en este código, por lo que no importa.
DLosc
fuente
8

JavaScript, 217 215 bytes

a="a=q;a=a.replace('q',uneval(a));for(b=c='a';d=a.split(c),c=d[Math.random()*~-d.length+1|0][0];b+=c);alert(b)";a=a.replace('q',uneval(a));for(b=c='a';d=a.split(c),c=d[Math.random()*~-d.length+1|0][0];b+=c);alert(b)

Tenga en cuenta que esto utiliza uneval, que solo es compatible con Firefox. Ejecuciones de muestra:

a=ale(a.lend[Ma=d[Macepla.ler(b+=c)b=q;fom(a=q;a=dort(b+1|0],c);a.lit(a)
at(c=c;d[0],c=q;ath+1|0][0];dorerac=ac=d[Ma),c;)*~-d[Ma=alenepl(b+=ac=c;a=c;d[2];d.re(c;fom()
a="a[0],und=d=a)
angt(b),und=d.l(b=a)
a)
ale(a.rth.revanepleplit(b)
ac);fore(b)*~-d.r(b+1|0];fora';a)*~-d.splalith+=dorth+=c=";ath+=a.length+=';ale(b)
a.r(b=c=a)b+1|0],und[0][0];d.splerath.spleneva)";ath.r(ceneplith+=d=aceple(c;)*~-d=';ala';)b='ac;fom(b=c;a.ler(b=d=d[Ma.rt(c=cendor()*~-d='a=";ac;a.spla)b=ceva=';a=d.rt(angt(alength+1|0],c;angt()
al(ac=dorth+1|0][0][0][0][Ma.split()

Como puede ver, es principalmente galimatías, pero eso es de esperarse;) El OP ha creado un JSFiddle que demuestra que la posibilidad de que una salida sea JS sintácticamente válida es aproximadamente 6.3%.


Si se permitieran funciones de lectura automática, esto podría ser 78 bytes de ES6:

f=(c="f",p=("f="+f).split(c),q=p[Math.random()*~-p.length+1|0][0])=>q?c+f(q):c

Muy, muy raramente, esto genera JS sintácticamente válido:

f=>e?c+f():c
f=>e?c=>engt():c
f=>e?c=(e):c
f=>e?c=>e=>ength.split():c
f=p=>q?c+f():c
f(q).sp=",p[Mat(q?c=(),plith.lith.sp.sp[0]).lendom().lith+f=>q=p.lendom(",p=p=>q?c+f():c
f(q),q?c=(c=(q)*~-p[0]):c
f().random(),q?c=(c=p[0]):c
f=>q?c=(q="+f"+f).rath.split(c):c
f="+1|0])=().lith.rat()*~-p=>q?c=p[Mat(c=",q?c=p.rath.splendom()*~-plength.splith.lendom(c):c

Mi favorito de los nombres de funciones que se crea es .splendom()( split+ length+ random)

ETHproducciones
fuente
3
Me pregunto cuál es la probabilidad de que esto genere JavaScript válido. (Advertencia de
francotirador de
2
@DanTheMan Ciertamente muy, muy bajo. La probabilidad de que todos los paréntesis y paréntesis estén equilibrados es increíblemente baja. Aunque una vez lo conseguí a.splerength.r(), lo que podría ser válido;)
ETHproductions
1
Es posible que desee señalar que esto es FF solo debido al uso de uneval
Shaun H
1
@ShaunH Gracias, olvidé que solo FF es compatible con uneval.
ETHproductions
55
La segunda función de auto lectura no es válida ( meta.codegolf.stackexchange.com/a/4878/48878 "un quine no debe acceder a su propia fuente, directa o indirectamente"), y @DanTheMan, según jsfiddle.net / kabkfLak / 1 , la probabilidad debería ser de alrededor del 6.3%.
Artyer
5

Perl, 103 bytes

Basado en el quine estándar y mi respuesta a esta pregunta :

$_=q{$_="\$_=q{$_};eval";@s='$';{push@s,(@n=/(?<=\Q$s[-1]\E)(.|$)/g)[rand@n];$s[-1]&&redo}print@s};eval

Salida de ejemplo

$_=q{$_=q{$_=";@sh@s=";eval
$_="\$_=q{$_='$_=q{$_}pus=\$_=";@n=";@ndo};{pus=';edo};@n]\Q$_};{$_};@s=q{$_=';@s[rand@s=/g)(@s,(@s,(@sh@s[-1];@ndo};ed@s[-1]\E)(.|$_}prevan]&ral";evan];{$_}pus='$_};ed@sh@sh@s[-1]\$_='$_};evando};eval
$_=q{$_=";ed@s[-1];evand@s="\Q$_=";@s[-1]\Q$_=q{$_=";@nd@sh@sh@s='$_=q{$_=q{$_='$_="\Q$_='$_};{pus=\$_=q{$_}pral
$_=";evando};@nd@sh@s,(@n]\$_=";@s,(@s[-1];{$_=q{$_}pral
$_=";eval
$_='$_=q{$_="\$_="\Q$_=";ed@sh@s=\E)(.|$_=q{$_=q{$_=q{$_=q{$_}pus=/(?<=q{$_};eval
$_=";ed@sh@s[-1]\Q$_=';edo};{$_=q{$_=";@nt@s,(@n]&&&&&&&ral";@nd@s,(@s[-1]\$_}pus=\E)(.|$_=';@nt@s[ral

De manera similar a la otra pregunta, algunos resultados generan Perl válido:

$_=q{$_};{$_};eval";@sh@s[-1]\$_='$_};evan]\Q$_}preval";eval
$_=q{$_};{$_=q{$_=';@nd@s=q{$_};@s[-1]\E)(@s[-1]\E)(@n=';edo};{$_}predo};eval
$_=q{$_=q{$_};edo};@n=q{$_=q{$_};@s[rin='$_=q{$_}pus=/g)(.|$_=q{$_};edo};eval
$_=q{$_};eval
$_=q{$_=";@ndo};{$_}preval

pero las posibilidades son ligeramente inferiores, a ~ 2%.

Dom Hastings
fuente
77
Si me dijeras que el primer ejemplo era válido, Perl te creería.
Ankh-Morpork 01 de
2
@ dohaqatar7 Al principio no entendí bien tu comentario y pensé que no me creerías si dijera que el código principal era válido Perl ...: D zoitz.com/comics/perl_small.png
Dom Hastings
@ ankh-morpork: es claramente inválido, q{es el comienzo de un literal de cadena y no hay }que cerrarlo. Perl en realidad es bastante malo para ejecutar secuencias aleatorias de bytes (y cuando lo hace, normalmente se debe a un literal de cadena o comentario temprano).
4

Código de máquina MS-DOS (archivo .COM), 63 bytes - no competidor

No compite porque una quine no debe acceder a su propio código fuente.

¡Una variante de 126 bytes cumpliría el requisito de "no acceder a su propio código fuente"!

La variante de 63 bytes se ve así:

FC BE 00 01 AC 50 88 C2 B4 02 CD 21 E8 1A 00 59
4E AC 81 FE 3F 01 7C 03 BE 00 01 38 C1 75 F2 FE
CA 75 EE 81 FE 00 01 75 DB 8A 16 00 80 31 C0 8E
D8 31 C9 AC 00 C2 E2 FB 0E 1F 88 16 00 80 C3

Tampoco estoy seguro acerca de la distribución de probabilidad del generador aleatorio:

El programa utiliza el hecho de que los contadores de reloj y otra información modificada por interrupciones se almacenan en el segmento 0 para generar números aleatorios.

Ejemplos de salidas generadas son:

FC BE 00 01 7C 03 BE 00 80 C3

FC BE 00 01 38 C1 75 F2 FE 00 80 31 C9 AC 81 FE 00 80 C3

FC BE 00 01 38 C1 75 EE 81 FE 00 01 38 C1 75 EE 81 FE CA
75 F2 FE 00 01 75 F2 FE 00 80 C3

FC BE 00 C2 B4 02 CD 21 E8 1A 00 01 7C 03 BE 00 59 4E AC
81 FE 3F 01 AC 81 FE 3F 01 7C 03 BE 00 01 7C 03 BE 00 01
AC 81 FE 3F 01 7C 03 BE 00 80 C3

Convertido a código de ensamblaje, el programa se ve así:

    cld                # Ensure SI is being incremented
    mov si, 0x100      # Move SI to the first byte of the program
nextOutput:
    lodsb              # Load one byte of the program ...
    push ax            # ... save it to the stack ...
    mov dl, al         # ... and output it!
    mov ah, 2
    int 0x21
    call pseudoRandom  # Create a random number (in DL)
    pop cx             # Take the stored byte from the stack
    dec si             # Go back to the last byte loaded
nextSearch:
    lodsb              # Load the next byte
    cmp si, programEnd # If we loaded the last byte ...
    jl notEndOfProgram # ... the next byte to be loaded ...
    mov si, 0x100      # ... is the first byte of the program.
notEndOfProgram:
    cmp cl, al         # If the byte loaded is not equal to ...
                       # ... the last byte written then ...
    jne nextSearch     # ... continue at nextSearch!
    dec dl             # Decrement the random number and ...
    jnz nextSearch     # ... continue at nextSearch until the ...
                       # ... originally random number becomes zero.
    cmp si, 0x100      # If the last byte read was not the last byte ...
    jnz nextOutput     # ... of the program then output the next ...
                       # ... byte!

    # Otherwise fall through to the random number generator
    # whose "RET" instruction will cause the program to stop.        

    # The random number generator:
pseudoRandom:
    mov dl, [0x8000]   # Load the last random number generated
                       # (Note that this is uninitialized when
                       # this function is called the first time)
    xor ax, ax         # We use segment 0 which contains the ...
    mov ax, ds         # ... clock information and other data ...
                       # ... modified by interrupts!
    xor cx, cx         # Prepare for 0x10000 loops so ...
                       # ... all bytes in the segment are processed ...
                       # ... once and the value of SI will be ...
                       # ... unchanged in the end!
randomNext:
    lodsb              # Load one byte
    add dl, al         # Add that byte to the next random number
    loop randomNext    # Iterate over all bytes
    push cs            # Restore the segment
    pop ds
    mov [0x8000], dl   # Remember the random number
    ret                # Exit sub-routine

programEnd:
Martin Rosenau
fuente
La no competencia está reservada para las respuestas que cumplen con los criterios del desafío, pero que utilizan un lenguaje o una característica más nueva que el desafío. Publique la variante que no lee su propia fuente o elimine la respuesta.
mbomb007
4

C, 306 328 585 611 615 623 673 707 bytes

Código fuente:

p[256][256]={0};char*X="p[256][256]={0};char*X=%c%s%c,Y[999],c,j,*a;main(){sprintf(Y,X,34,X,34);for(a=Y;*a;a++)p[*a][*(a+1)]++;for(j=*Y;putchar(c=j);)while(p[c][++j]<<16<rand());}",Y[999],c,j,*a;main(){sprintf(Y,X,34,X,34);for(a=Y;*a;a++)p[*a][*(a+1)]++;for(j=*Y;putchar(c=j);)while(p[c][++j]<<16<rand());}

Con nuevas líneas y espacios en blanco agregados para legibilidad / explicación:

01  p[256][256]={0};
02  char*X="p[256][256]={0};char*X=%c%s%c,Y[999],c,j,*a;main(){sprintf(Y,X,34,X,34);for(a=Y;*a;a++)p[*a][*(a+1)]++;for(j=*Y;putchar(c=j);)while(p[c][++j]<<16<rand());}",
03  Y[999],c,j,*a;
04  main(){
05      sprintf(Y,X,34,X,34);
06      for(a=Y;*a;a++)p[*a][*(a+1)]++;
07      for(j=*Y;putchar(c=j);)
08          while(p[c][++j]<<16<rand());
09  }

Explicación

Line 01: p[][]contiene los recuentos de un personaje que sigue a otro.

Line 02: Xcontiene la fuente del programa, escapado con %c%s%c.

Line 03: Ycontendrá la fuente literal del programa. c, j, *aSon las variables de recuento.

Line 05: Configurado Ypara contener la quine.

Line 06: Cuenta las apariciones de letras en p[][].

Line 07: Imprime el estado actual.

Line 08: Encuentra el siguiente personaje al azar, proporcional a los recuentos en p[][].

Salida de muestra:

p[++);p[99]=Y;putfor(aind(a++j,*a+j=j,c][c,*an(arile(pr*Y,Y[256]<<1);)][*Y,Y;)wha+++j=*aintfor*Y;prin(a+j]=j][256<1)pr(a;a;f(p[char(Y;for());};a;ma;ma=%s%chain(Y;ar(j][256<<<1)p[256<<raile(cha][9]<rin(j,34,34,Y[256]+j,Y,34,Y,c=Y,*a;*a;for(){0}


fuente
1
¿Puede agregar una versión sin líneas nuevas y espacios en blanco para que podamos verificar el recuento de bytes?
Steven H.
1
Sí, he agregado la versión de línea única en la parte superior.
3

Ruby, 152 bytes

0;s="0;s=%p<<33
0until putc($/=Hash[[*(s%%s).chars.each_cons(2)].shuffle][$/])==?"<<33
0until putc($/=Hash[[*(s%s).chars.each_cons(2)].shuffle][$/])==?!

Salida de muestra:

0;s.c($/=Has(s).ears(2).ch[*(2)=Hacontc(2).ears.eas=Has==Hars%putc($/]).ears%sh_chuffl puns=Hachach[$/==?!

o

0;s.ch[*($/=%pufl puns($/=%s.shas($/=Harsh_chutilears)])].e]).s)=Hac($/=="<<33\ntile].chufffle][[$/=Hars%sh_c(2)=%p<<<<<33
0;s)].ears)=Hars).c(s).eacon0un0;sh_c($/][*(s.s=Hacons=?!

Quines usa el formato de cadena a través de "s%s", y hace el encadenamiento de Markov al tomar todas las rebanadas de dos caracteres, mezclarlas y convertirlas en un diccionario Hash, donde para las claves duplicadas la última aparición define el valor. Para evitar agregar lógica adicional para el comienzo, sigo el último carácter de salida usando $/, que se inicializa automáticamente en una nueva línea, y me aseguro de que las nuevas líneas siempre estén seguidas en el código por 0el mismo carácter con el que comienza el código. Para el final, manipulo el código fuente para que solo haya uno, de !modo que siempre terminemos después de la explosión, usando <<33para agregarlo sin el literal. Esto podría desarrollarse aún más utilizando un carácter de un solo dígito no imprimible en lugar de ASCII 33, pero eso parecía demasiado molesto.

histocrat
fuente
44
p<<<<<33¿El operador super-super-super-concat? ;-)
ETHproductions
3
Ese es el operador "muuuucho menos que".
mbomb007
2
¡Me encantan las palabras que esto genera! ¡El hecho de que el primer ejemplo es tan preocupante si el objeto Has(s).ears(2)me hace reír!
Dom Hastings
2

Óxido, 564 bytes (no competitivo)

extern crate rand;fn main(){let t=("extern crate rand;fn main(){let t=", ";let mut s=format!(\"{}{:?}{}\",t.0,t,t.1).into_bytes();s.push(0);let mut r=rand::thread_rng();let mut c=s[0];while c!=0{print!(\"{}\",c as char);let u=s.windows(2);c=rand::sample(&mut r,u.filter(|x|x[0]==c),1)[0][1];}}");let mut s=format!("{}{:?}{}",t.0,t,t.1).into_bytes();s.push(0);let mut r=rand::thread_rng();let mut c=s[0];while c!=0{print!("{}",c as char);let u=s.windows(2);c=rand::sample(&mut r,u.filter(|x|x[0]==c),1)[0][1];}}

Como ya había escrito un quine de Rust bastante limpio para otra pregunta, pensé en adaptarlo para esto, ya que parecía bastante simple. Aunque el original era pequeño, sin embargo, para esto he hecho muy pocos intentos de minimizar el tamaño. Aquí hay una versión ampliada para explicar lo que está sucediendo:

// Random numbers are removed from the standard library in Rust,
// I had to make a cargo project to even compile this...
// Rust is hardly a golfing language.
extern crate rand;

fn main(){

    // The quine is fairly simple, we just make a tuple with 
    // "everything before this tuple" as first element, and
    // "everything after this tuple" with any quotes escaped 
    // as second. That makes it really easy to print.
    let t=("[...before...]", "[...after...]");

    // Instead of printing it, we save it as a byte vector
    // and append 0
    let mut s=format!("{}{:?}{}",t.0,t,t.1).into_bytes();
    s.push(0);

    // Start with the first character
    let mut c=s[0];
    let mut r=rand::thread_rng();

    while c!=0 {
        print!("{}",c as char);

        // We slide a 2 wide window over it to save a vector
        // of all bigrams. 
        let u=s.windows(2);

        // Filter it to only those which have the current character 
        // as first. Take one at random, its second is our next 
        // character.
        c=rand::sample(&mut r, u.filter(|x|x[0]==c), 1)[0][1];

        // Keep at it until the 0 byte is generated.
    }
}

Salida de muestra 1:

eran(),0{ller=samarin chas c).pr,teteran mut madoletet manthilaplerng().wind_byt.wit();let.u.0][*s=[*s.plleas.wshit, rnd:Vec<_byte mputextet ut t leat=r,t rant!=r().filllet rng();lar("{}{let.ind_byt.what amusarando_ramut!=st ct!(\").0]=colet!(&lec<_ret.plec=s.whrararandormpr=saile ret=r,0]=r);le(\"),t und;fint.prilt!();ler(2).forap(&ler=s(),t ut rat mu:t=ramund:Ve s.putec==[0];wst and_byt sh(\"et c s[1), munwhras[0];c=s=s="etornws(2)[0, ain(|x|x[0,0,0];fowile c ct(&l=",tes().co_byt().wrmat ash(|x|x[*s.lethrant.wrarmu.file(\"et, r==[1);uterile().0,t ando_rinwhas=[0{}"ect.wilant!("{ple mut, mut mamprmant,0];le(&lec=s.1),t co_>=fin mamustec!(\",c=[0];}}",0];leteteat.ust(",ternwhashrarmut ler("erat,0]==file and_reter==s.utet an letet.ut=", ras.1);fin("{:?}"et t letes[*sado_bytet rnd::Verain s[0];whant(){}{}\"echin s(2);lerad;wst reth(\",t u.iletermat c 1];}{}

Salida de muestra 2:

et!().0][0][0{}
Harald Korneliussen
fuente
2

Python 2, 211 bytes

Emite el resultado a stderr.

import random;X='q=[(list(t)+["$$"])[i+1]for i in range(len(t))if t[i]==c];c=random.choice(q)\nif c=="$$":exit(o)\no+=c\nexec X';s='import random;X=%r;s=%r;q=t=s%%(s,X);o=c="i";exec X';q=t=s%(s,X);o=c="i";exec X

Pruébalo en línea

Salida de muestra:

i+[(s,X)));exenit(or;q=rt(t(t(t);o='ic\n(q)+1]=c\ndor randort))\ngeno));X)\nge(st))ic]=";oic=%ran(s%%(s%rt(q)\ngexe(s=st(t[(s=[if X=%(ompoiforanom;e(t X="$"$"ic="$"i";X=c rt X

Breve explicacion:

  • Este programa usa el s='s=%r;print s%%s';print s%sformato quine. Creo una cadena sque contendrá todo el programa.
  • La cadena Xcontiene el procedimiento para ejecutar recursivamente.
  • El procedimiento crea la cadena de salida o, que se imprimirá enstderr al llegar al final de la cadena de Markov.
  • El final de la cadena está representado por la cadena $$, usando dos caracteres para que el programa funcione para todas las cadenas. Podría haber usado un personaje que no está en mi programa comochr(0) , pero creo que es más largo.
  • Se coloca el carácter elegido en cada ejecución c, que (junto cono ) se inicializa en el primer carácter del programa.
  • La lista de caracteres que sigue a cada aparición de elección cen la cadena t(la variable que contiene la quine del código fuente) es q, que se elegirá para la próxima selección de c.
mbomb007
fuente
1

PHP, 144 135 130 120 272 220 212 bytes

<?$e='$p=$n="";foreach(str_split($s)as$w)$p=$m[$p][]=$w;do echo$n=$m[$n][array_rand($m[$n])];while("\n"!=$n);
';$s='<?$e=%c%s%1$c;$s=%1$c%s%1$c;$s=sprintf($s,39,$e,$s);eval($e);';$s=sprintf($s,39,$e,$s);eval($e);

O, formateado para facilitar la lectura:

<?$e='$p = $n = "";
foreach (str_split($s) as $w) {
    $p = $m[$p][] = $w;
}
do {
    echo $n = $m[$n][array_rand($m[$n])];
} while ("\n" != $n);
';$s='<?$e=%c%s%1$c;$s=%1$c%s%1$c;$s=sprintf($s,39,$e,$s);eval($e);';$s=sprintf($s,39,$e,$s);eval($e);

Salida de muestra:

<?p=')ay_r_gecorr_splililen]=$p=$w;

y:

<?p=$n=$ntststs$m[$n=$m[ay_r_chondo$n=$ph(s$nt(fitstr_r_geantentr_s('m[$n=$n"!=$p etstsp][$w;d(fililile(s$w)$nt(sphor_str_getrarast(''''m[$n='m[$m';

y:

<?p=$who eay_re($n=$n=$nt(')];d(fililileando et($m[]=$pleay_ch(')aray_ren='''))ay_st_r_s($m[$m[asp])ay_co$m[$p $phorentechitr_rean)][$n=$nd("\n"!=$n=$wh(filend('')ay_gen=$ndo$nt_rasp=$n][$p=$whp=$n='m[$n"\n)))))][$w;dorechph(';dorracho$ple_s$w;fil

y:

<?ph($n);

PHP trampa, 117

Para los curiosos, si hacemos trampa leyendo nuestra propia fuente, podemos hacer 117:

<?=$p=$n='';foreach(str_split(file('m')[0])as$w)$p=$m[$p][]=$w;do echo$n=$m[$n][array_rand($m[$n])];while("\n"!=$n);
Paraguas
fuente
Bienvenido al sitio! Desafortunadamente, tenemos algunas reglas sobre lo que cuenta como un Quine adecuado para desafíos como este y desafortunadamente está prohibido leer de su propia fuente.
Post Rock Garf Hunter
Oh bien, gracias. Estaba buscando las reglas. Tendré que revisar esto.
Umbrella