Markov Chain Quine

17

W tym pytaniu zostanie zastosowany prosty model Markowa. Aby uzyskać więcej informacji o łańcuchach Markowa, zobacz http://setosa.io/ev/markov-chains/ .

Weź sznurek. W tym przykładzie użyjemy słowa:

reader

Teraz dla każdego znaku weź znaki, które pojawiają się po każdym wystąpieniu znaku w ciągu. ( ​`^`​reprezentuje początek ciągu i ​`$`​reprezentuje koniec)

`^` -> {'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'}

Teraz, zaczynając od początku ciągu, wybierz losowo jedną z postaci w następnym zestawie. Dołącz tę postać, a następnie wybieraj postacie z następnego zestawu i tak dalej, aż dojdziesz do końca. Oto kilka przykładowych słów:

r
rereader
rer
readereader

Jeśli postać pojawia się wielokrotnie za inną postacią, jest bardziej prawdopodobne, że zostanie wybrana. Na przykład, cocoa canpo c, istnieje dwie trzecie szans na uzyskanie oi jedna trzecia szansy na uzyskanie a.

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

Wyzwanie

Utwórz program, który nie pobiera danych wejściowych i generuje losowy ciąg wygenerowany za pomocą łańcucha Markowa, jak powyżej, gdzie dane wejściowe do łańcucha są źródłem programu.

  1. Program musi mieć co najmniej dwa znaki, z których dwa muszą być takie same (aby zapobiec „nudnym” łańcuchom, które mają tylko jedno wyjście)
  2. Możesz zmodyfikować model, aby używać bajtów zamiast znaków, jeśli chcesz, ale zmień „znaki” na „bajty” w regule 1
  3. Program powinien wyprowadzać ciągi losowo z teoretyczną częstotliwością oczekiwaną

To jest , więc wygrywa najkrótszy program!

Artyer
źródło
@ mbomb007 wszystkie informacje są w pytaniu, link jest tylko dodatkowy, jeśli się zainteresujesz (Jest to bardzo podstawowa implementacja)
Artyer
3
Dlaczego ^i $w cudzysłowie? może to uczynić bardziej zrozumiałym wyciąganie go z cytatów lub umieszczanie ich w cudzysłowie.
Destructible Lemon

Odpowiedzi:

6

Pypeć , 64 bajty

To było fajne.

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

<tab>reprezentuje dosłowny znak tabulacji ( 0x09). Wypróbuj online!

W jaki sposób?

TL; DR: składnia łańcucha znaków, repr i eval.

W przypadku ciągów, które muszą zawierać literalne "znaki, Pip uniknął ciągów znaków , używając ich \"jako separatora. Standardowy quine wykorzystujący łańcuchy znaków będzie wyglądał następująco:

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

To znaczy: Yank (przechowujący jako y) ciąg zawierający "V Y".RPyi Vtak dalej. RPypobiera repr y, do którego przygotowujemy dosłowny ciąg V Y. Na koniec wypisz wynik eval.

Struktura quinu Markowa jest podobna, z tym wyjątkiem, że chcemy zapisać kod zamiast wypisywać go, a następnie zrobić z nim kilka rzeczy później. t:V Y\"...\"przypisuje ostateczny wynik do t. Wewnątrz ewaluowanego kodu m:"..."przypisuje ciąg kodu, do mktórego oceniamy na końcu Vm.

ST["t:V Y"RPy";Vm"C9] buduje listę zawierającą

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

i konwertuje go na ciąg znaków, który domyślnie łączy wszystkie elementy. Ta sekcja jest równoważna "V Y".RPyoryginalnej wersji Quine. Ponieważ jest to ostatnie wyrażenie w dużym ciągu eval, jego wartością jest to, co Vzwraca operator, a zatem to, do czego zostaje przypisane t.

Zatem po ewaluacji i przypisaniu tjest równa pełnemu kodowi i mzawiera

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

Teraz Vmocenia to jako kod. Podzielmy to, co się stanie.

                            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

Kilka notatek:

  • Zakończenie kodu literalną literą było krótsze niż wykonanie wyrażenia regularnego dla „następnego znaku lub końca łańcucha”.
  • Wyrażenie regularne, którego użyłem, nie działa poprawnie, jeśli w kodzie są podwójne znaki; na przykład zastosowanie go do xxyzwróci tylko, xxa nie xyw dopasowaniach. Na szczęście w tym kodzie nie ma jednak podwójnych znaków, więc nie ma to znaczenia.
DLosc
źródło
8

JavaScript, 217 215 bajtów

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)

Pamiętaj, że używa tego uneval, który jest obsługiwany tylko przez Firefox. Przykładowe przebiegi:

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

Jak widać, jest to w większości bełkot, ale należy się tego spodziewać;) OP stworzył JSFiddle, który pokazuje, że szansa na poprawność syntaktyczną JS wynosi około 6,3%.


Gdyby dozwolone były funkcje samo-odczytu, może to być 78 bajtów ES6:

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

Bardzo, bardzo rzadko, powoduje to, że JS jest poprawny pod względem składniowym:

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

Moim ulubionym z utworzonych nazw funkcji jest .splendom()( split+ length+ random)

ETHprodukcje
źródło
3
Zastanawiam się, jakie jest prawdopodobieństwo wygenerowania prawidłowego kodu JavaScript. (Ostrzeżenie
snajperskie
2
@DanTheMan Z pewnością bardzo, bardzo niski. Prawdopodobieństwo wyważenia wszystkich nawiasów i nawiasów jest niewiarygodnie niskie. Chociaż raz dostałem a.splerength.r(), co może być ważne;)
ETHprodukcje
1
Być może chcę zauważyć, że jest to FF tylko z powodu nierównomierności
Shaun H
1
@ShaunH Dzięki, zapomniałem, że tylko FF obsługuje nierówność.
ETHprodukcje
5
Druga funkcja samo-czytania jest niepoprawna ( meta.codegolf.stackexchange.com/a/4878/48878 „quine nie może uzyskać dostępu do swojego źródła, bezpośrednio lub pośrednio.”) I @DanTheMan, zgodnie z jsfiddle.net / kabkfLak / 1 , szansa powinna wynosić około 6,3%.
Artyer
5

Perl, 103 bajty

W oparciu o standardowy quine i moją odpowiedź na to pytanie :

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

Przykładowy wynik

$_=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

Podobnie jak inne pytanie, niektóre wyniki generują poprawny Perl:

$_=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

ale szanse są nieco niższe i wynoszą ~ 2%.

Dom Hastings
źródło
7
Gdybyś powiedział mi, że pierwszy przykład jest ważny, Perl, uwierzyłbym ci.
ankh-morpork
2
@ dohaqatar7 Na początku źle zrozumiałem twój komentarz i pomyślałem, że nie uwierzysz, gdybym powiedział, że główny kod jest prawidłowy Perl ...: D zoitz.com/comics/perl_small.png
Dom Hastings
@ ankh-morpork: jest wyraźnie niepoprawny, q{jest początkiem literału łańcucha i nie ma go, }aby go zamknąć. Perl jest właściwie dość kiepski w uruchamianiu losowych sekwencji bajtów (a kiedy to robi, zwykle dzieje się tak z powodu wczesnego literału lub komentarza).
4

Kod maszynowy MS-DOS (plik .COM), 63 bajty - niekonkurujący

Nie konkuruje, ponieważ quine nie może uzyskać dostępu do własnego kodu źródłowego.

Wariant 126-bajtowy spełniałby wymóg „nie uzyskiwania dostępu do własnego kodu źródłowego”!

63-bajtowy wariant wygląda następująco:

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

Nie jestem również pewien rozkładu prawdopodobieństwa generatora losowego:

Program wykorzystuje fakt, że liczniki zegara i inne informacje zmodyfikowane przez przerwania są przechowywane w segmencie 0 w celu wygenerowania liczb losowych.

Przykłady generowanych wyników to:

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

Program przekonwertowany na kod asemblera wygląda następująco:

    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
źródło
Niekonkurencyjny jest zarezerwowany dla odpowiedzi, które spełniają kryteria wyzwania, ale używają języka lub funkcji nowszej niż wyzwanie. Opublikuj wariant, który nie czyta własnego źródła, lub usuń odpowiedź.
mbomb007
4

C 306 328 585 611 615 623 673 707 bajty

Kod źródłowy:

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

Z dodanymi znakami i białymi znakami dla czytelności / objaśnienia:

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  }

Wyjaśnienie

Line 01: p[][]przechowuje liczby kolejnych znaków.

Line 02: Xzawiera źródło programu, wraz z klawiszem Esc %c%s%c.

Line 03: Ybędzie zawierał dosłowne źródło programu. c, j, *aSą zmiennymi liczenia.

Line 05: Zestaw Yzawiera quine.

Line 06: Policz wystąpienia liter w p[][].

Line 07: Wydrukuj bieżący stan.

Line 08: Znajdź następną postać losowo, proporcjonalnie do liczby p[][].

Przykładowe dane wyjściowe:

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}


źródło
1
Czy możesz dodać wersję bez nowego wiersza i białych znaków, abyśmy mogli zweryfikować liczbę bajtów?
Steven H.,
1
Tak, dodałem wersję jednowierszową u góry.
3

Rubin, 152 bajty

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][$/])==?!

Przykładowe dane wyjściowe:

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

lub

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 używa formatowania łańcuchów przez "s%s"i wykonuje łańcuch Markowa, biorąc wszystkie dwuznakowe plastry, tasując je i przekształcając w słownik Hash, w którym dla duplikatów kluczy ostatni wygląd określa wartość. Aby uniknąć dodawania dodatkowej logiki na początku, śledzę ostatnio używany znak wyjściowy $/, który jest automatycznie inicjowany do nowej linii, i upewniam się, że po linii nowej zawsze następuje po 0tym samym znaku, od którego zaczyna się kod. Na koniec manipuluję kodem źródłowym, aby był tylko jeden, !więc zawsze kończymy po huku, <<33dodając go bez literału. Można to jeszcze pograć w golfa za pomocą jednocyfrowego znaku niedrukowalnego zamiast ASCII 33, ale wydawało się to zbyt denerwujące.

histocrat
źródło
4
p<<<<<33Operator super-super-super-konkat? ;-)
ETHproductions
3
To jest operator „waaaay mniej niż”.
mbomb007
2
Uwielbiam słowa, które to generuje! Fakt, że pierwszy przykład jest taki niepokojący, jeśli obiekt Has(s).ears(2)wywołuje u mnie chichot!
Dom Hastings,
2

Rdza, 564 bajty (niekonkurencyjne)

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];}}

Ponieważ napisałem już całkiem porządny cytat z Rust na inne pytanie, pomyślałem, że dostosuję go do tego, ponieważ wydawało się to dość proste. Chociaż oryginał był niewielki, w tym celu bardzo mało próbowałem zminimalizować rozmiar. Oto rozszerzona wersja wyjaśniająca, co się dzieje:

// 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.
    }
}

Przykładowy wynik 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];}{}

Przykładowe wyjście 2:

et!().0][0][0{}
Harald Korneliussen
źródło
2

Python 2, 211 bajtów

Wysyła wynik do 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

Wypróbuj online

Przykładowe dane wyjściowe:

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

Krótkie wyjaśnienie:

  • Ten program używa s='s=%r;print s%%s';print s%sformatu quine. Tworzę ciągs , który będzie zawierał cały program.
  • Ciąg X zawiera procedurę rekurencyjną.
  • Procedura buduje ciąg wyjściowy o, do którego zostanie wydrukowany stderrpo osiągnięciu końca łańcucha Markowa.
  • Koniec łańcucha jest reprezentowany przez ciąg $$, używając dwóch znaków, dzięki czemu program będzie działał dla wszystkich ciągów. Mógłbym użyć postaci, której nie ma w moim programie chr(0), ale myślę, że to dłużej.
  • Umieszczony jest znak wybrany przy każdym wykonaniu c, który (wraz z o) jest inicjowany do pierwszego znaku programu.
  • Lista znaków, które występują po każdym wystąpieniu wyboru cw ciągu t(zmienna zawierająca quine kodu źródłowego) to q, z której wybierany będzie następny wybór c.
mbomb007
źródło
1

PHP, 144 135 130 120 272 220 212 bajtów

<?$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);

Lub sformatowane pod kątem czytelności:

<?$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);

Przykładowe dane wyjściowe:

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

i:

<?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';

i:

<?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

i:

<?ph($n);

Oszukiwanie PHP, 117

Dla ciekawskich, jeśli oszukujemy czytając własne źródło, możemy zrobić 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);
Parasol
źródło
Witamy na stronie! Niestety, mamy pewne zasady dotyczące tego, co uznaje się za właściwy Quine dla takich wyzwań i niestety czytanie z własnego źródła jest zabronione.
Post Rock Garf Hunter
Och, dobrze, dziękuję. Szukałem zasad. Będę musiał to zrewidować.
Parasol