Program, który drukuje programy


13

Wyzwanie

Twoim celem jest napisanie programu, który wydrukuje inny program. Ten wydrukowany program powinien wydrukować inny program, a nowy program powinien wydrukować inny program, aż do końca.

Zasady

  1. Każdy program musi mieć mniej niż 256 bajtów. (Jeśli trzeba to zmienić, zostaw komentarz)
  2. Ostatni program musi być pustym programem.
  3. Musi istnieć skończona liczba programów, więc program nie może być quine.
  4. Wszystkie programy muszą działać w tym samym języku.
  5. Wejście nie jest dozwolone.
  6. Zwycięski program to program, który drukuje tyle programów, ile to możliwe, sam się licząc.

Powodzenia!


Maksymalny wynik to 2^2048lub 3.2317e616.
orlp

Aby ułatwić porównywanie dużych wyników, podaj przybliżenie swojego wyniku w postaci, a*10^bgdzie 1<=a<10i bjest liczbą naturalną.
flawr

2
Właściwie moje poprzednie obliczenia były błędne. Zakładając, że program musi być w bajtach, maksymalny możliwy wynik to <liczba za długa do komentarza> lub 1.2673e614.
orlp

Odpowiedzi:


20

CJam, 4,56 x 10 526 programów

2D#2b{"\256b_(256b:c'\s`_:(er`":T~{;38'ÿ*`{:T~{;63'ÿ*`{:T~{;88'ÿ*`{:T~{;114'ÿ*`{:T~{;140'ÿ*`{:T~{;166'ÿ*`{:T~{;192'ÿ*`{:T~{;219'ÿ*`{Q?\"_~"}s(\T}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}_~

Dokładny wynik: 254 219 + 254 192 + 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 3

Wszystkie programy muszą zostać zapisane przy użyciu kodowania ISO-8859-1, aby zachować zgodność z limitem rozmiaru pliku.

Dzięki @ChrisDrost, który zwrócił uwagę na błąd i zasugerował sposób zagnieżdżenia.

Wypróbuj online w interpretatorze CJam .

254 219 + 2 ≈ 4,56 × 10526 programów

Podział wyniku na linię można osiągnąć w następującym, znacznie prostszym programie 1 .

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"
{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

Uruchomienie tego programu powoduje powstanie programu

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ"
{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

a po 254 219 - 1 kolejnych iteracjach program

{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

Ten ostatni niepusty program kończy działanie z błędem 2 i nic nie drukuje (pusty program).

Jak to działa

Załóżmy, że łańcuch jest już na stosie.

{      e# Push a code block.
  \    e# Swap the string on top of the code block.
       e# This will cause a runtime error if there is no string on the stack.
  256b e# Convert the string (treated as a base-256 number) to integer (I).
  _(   e# Copy the integer and decrement the copy.
  256b e# Convert the integer into the array of its base-256 digits.
  :c   e# Cast each base-256 digit to character. Converts from array to string.
  '\s  e# Push a string that contains a single backslash.
  `    e# Push its string representation, i.e., the array ['" '\ '\ '"].
  _:(  e# Push a copy and decrement each character. Pushes ['! '[ '[ '!].
  er   e# Perform transliteration to replace "s with !s and \s with [s.
       e# This skips characters that require escaping.
  `    e# Push its string representation, i.e., surround it with double quotes.
  Q    e# Push an empty string.
  ?    e# Select the first string if I is non-zero, the empty string otherwise.
  \    e# Swap the selected string with the code block.
  "_~" e# Push that string on the stack.
}      e#
_~     e# Push a copy of the code block and execute it.
       e# The stack now contains the modified string, the original code block
       e# and the string "_~", producing an almost exact copy of the source.

254 192 ≈ 5,35 × 10 461 innych programów

To tutaj trochę się wariuje.

Pierwszy program jest wysoce ściśliwy. Pisząc podobny program, który zamiast pustego programu ostatecznie tworzy pierwszy program z powyższej sekcji, możemy poprawić wynik o 254 192 programów 3 .

Program

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"
{"\256b_(256b:c'\s`_:(er`":T~{;219'ÿ*`{Q?\"_~"}s(\T}?\"_~"}_~

jest podobny do pierwszego programu z poprzedniej sekcji, a uruchomienie pierwszego i jego wyniku dla 254 192 iteracji powoduje powstanie drugiego.

Załóżmy, że ciąg znaków znajduje się już na stosie:

{                           e# Push a code block.
  "\256b_(256b:c'\s`_:(er`" e# Push that string on the stack.
                            e# The characters inside it behave exactly as
                            e# they did in the previous section.
  :T~                       e# Save the string in T and evaluate it.
  {                         e# If the integer I is non-zero, keep the generated
                            e# string; else:
    ;                       e#   Pop the code block from the stack.
    219'ÿ*`                 e#   Push a string of 219 ÿ's (with double quotes).
    {Q?\"_~"}               e#   Push that block on the stack.
    s                       e#   Push its string representation.
    (\                      e#   Shift out the { and swap it with the tail.
    T                       e#   Push T.
  }?                        e#
  \                         e# Swap the selected string with the code block
                            e# or T with the tail of the code block.
  "_~"                      e# Push that string on the stack.
}                           e#
_~                          e# Push a copy of the code block and execute it.

Programy Moar

Pierwszy program z poprzedniej sekcji jest nadal wysoce ściśliwy, więc możemy zastosować podobną metodę i napisać program, który po 254 166 iteracjach tworzy wspomniany program.

Powtarzając tę ​​technikę w kółko, dopóki nie osiągniemy limitu 255 bajtów, możemy dodać w sumie 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 1 ≈ 1,59 × 10 399 programów do te z poprzednich sekcji.


Dodano 1 nową linię dla przejrzystości.
2 Na konsensus w sprawie Meta , jest to domyślnie dozwolone.
3 lub 0,00000000000000000000000000000000000000000000000000000000000000%



5

JavaScript, 1000 programów

x=999;
q=";alert(x=999?`q=${JSON.stringify(q)+q}`.split(x).join(x-1):``)";
alert(
    x ? `x=999;q=${JSON.stringify(q)+q}`.split(x).join(x-1) // basically .replaceAll(x, x-1)
      : ``
)

To, czy jest to ważne, zależy od tego, jak dokładnie zrozumieć trzecią zasadę.


Z technicznego punktu widzenia nie jest to quine, ponieważ drukuje zmodyfikowaną wersję własnego kodu źródłowego zamiast identycznej kopii. Oczywiście wykorzystuje techniki podobne do quine. Myślę, że będziemy potrzebować wyjaśnień od @TheTurtle.
JohnE

5
@JohnE i Ypnypn Jest to coś takiego, jak sobie wyobrażałem. To działa.
Turtle

6
Nadal jesteś znacznie poniżej limitu długości kodu. Dlaczego nie zmienisz 999 na coś większego?
DankMemes,

4

Ruby, 1.628 × 10 ^ 237 programów

a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;_="a=%#x-1;_=%p;puts _%%[a,_]if a";puts _%[a,_]if a

Takie samo podejście jak moja odpowiedź na Perla, ale ponieważ Ruby już obsługuje duże ints, łatwiej jest przechowywać jako hex.


Ruby, 9.277 × 10 ^ 90 programów

a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;b=0xf;(b<1)&&(a-=1)&&b=eval('0x'+'f'*(74-("%x"%a).length));_="a=%#x;b=%#x;(b<1)&&(a-=1)&&b=eval('0x'+'f'*(74-('%%x'%%a).length));_=%p;puts _%%[a,b-1,_]if a";puts _%[a,b-1,_]if a

Więc ta próba jest nieco inną odmianą w porównaniu do poprzedniej wersji quine, ale ze względu na wszystkie dodatkowe funkcje nie dostaję liczby tak blisko jak ta druga ... Ciekawe było jednak spróbować innego podejścia!


4

Programy w języku Python 2, 9,7 * 10 ^ 229

O=0
if len(hex(O))<191:print"O=0x%x"%(O+1)+open(__file__).read()[-68:]

Fajnie, nie myślałem o powtórzeniu struny!
Dom Hastings,

2

C, 2,2 * 10 ^ 177 programów

#define S(s)char*q=#s,n[]="#####################################################################################################";i;s
S(main(){while(n[i]==91)n[i++]=35;i==101?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})

To nie jest idealne, ale całkiem dobre. Mam na myśli, że ma dokładnie 255bajty długości i generuje programy o tej samej długości. Prawdopodobnie mógłbyś jeszcze trochę pobawić się, aby uzyskać więcej programów, ale na razie zostawię to tak, jak jest.

Program oparty jest na prostym języku C. Dodatkowo istnieje dość prosty algorytm liczenia, który zlicza wszystkie możliwe wartości tablicy char n. Mamy tyle programów, ile permutacji ciągu n.

Zakres znakowania jest ograniczony do zakresu od #(= 35) do [= (91). To dlatego, że nie chcę żadnego "ani \ciągu, ponieważ trzeba ich uciec.

Generowanie programu kończy się, gdy wszystkie wartości w tablicy char n[. Następnie wyświetla prosty program zastępczy main(){}, który sam nic nie wypisuje.

#define  S(s) char *q = #s; /* have the source as a string */ \
char n[] = "#####################################################################################################"; \ 
int i; \
s /* the source itself */
S(main() {
    while(n[i]=='[') /* clear out highest value, so next array element be incremented */
        n[i++]='#'; 
    i==101 /* end of array reached? output dummy program */
        ? q = "main(){}"
        : n[i]++; /* count one up in the whole array */
    printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)", n, q);
})

Jako demonstracja, że powinien on pracować Właśnie zmienił granice, więc tylko znaki ASCII-Code 35i 36są używane i tylko 4 elementy tablicy.

Powstałe programy to

% echo > delim; find -iname 'program_*.c' | xargs -n1 cat delim

#define S(s)char*q=#s,n[]="####";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$###";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$##";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$##";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="##$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$#$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="###$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$##$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$#$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$#$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="##$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$#$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="####";i;s
S(main(){})

Daje to 2^4 + 1 = 17różne programy.

Tak więc powyższy program generuje ((91-35)+1)^101 + 1 = 57^101 + 1 ~= 2.2 * 10^177różne programy. Nie jestem całkowicie pewien, czy to się liczy, czy nawet moje obliczenia są prawidłowe


1
Czy możesz podać, że chodzi o 2.2 * 10^177(dla tych, którzy chcą porównać)?
flawr

Nie wiedziałem, jak to obliczyć, ale
załączyłem


1

Perl, 1 × 10 ^ 163

W przeciwnym razie jest to dość podstawowy quine, zredukowany do jak najmniejszej liczby znaków, który działa tylko wtedy, gdy licznik nie 0.

use bigint;$i=9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999||die;$_=<<'e';eval
print"use bigint;\$i=$i-1||die;\$_=<<'e';eval
${_}e
"
e

1

Common Lisp, 10 113 -1

(LET ((X
       99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999))
  (WHEN #1=(PLUSP X)
    #2=(SETF *PRINT-CIRCLE* T)
    #3=(PRINT (LIST 'LET `((X ,(1- X))) (LIST 'WHEN '#1# '#2# '#3#)))))
  • Jest 113 dziewiątek.
  • Następny program ma 112 dziewiątek, a następnie 8
  • Następny program ma 112 dziewiątek, a następnie 7
  • ...

Liczba dziewiątek jest ograniczona przez maksymalny rozmiar kodu, 256, biorąc pod uwagę spacje wprowadzone przez drukarkę.


1

Perl, 1,4 * 10 ^ 225

use bignum;open$F,__FILE__;$_=<$F>;s/0x\w+/($&-1)->as_hex/e;0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&&print

Podobne podejście do Pythona; ten sam wynik!


0

> <> , 65534 (?) Programy

Dodałem znak zapytania obok 65533, ponieważ muszę jeszcze zweryfikować, czy można wydrukować 65533 (chociaż mam powody, by sądzić, że powinien). Kiedy będę miał trochę więcej czasu, wymyślę sposób, aby to przetestować.

":?!;1-r00gol?!;a0.�

Możesz spróbować online tutaj .

Istotą tego programu jest to, że zmienia on wyjście znaku na samym końcu, a następnie zmniejsza jego wartość liczbową przed wydrukowaniem. Mam 65534 programy, ponieważ wartość ascii znaku na końcu kodu to 65533, więc licząc pierwszy program, mamy 65534 (jeśli liczyć pusty program 65535, tak myślę). Ostatni „zwrócony” program jest niczym; kończy się po prostu, gdy wartość znaku wynosi 0.

Jestem pewien, że będzie w stanie wydrukować znak dla wszystkich iteracji: Nie mogłem znaleźć ostatecznego źródła dla liczby znaków> <>, które można wydrukować, ale są liczby bezpośrednio poniżej 65533, liczbowo.

Daj mi znać, jeśli występują jakiekolwiek problemy z tym wdrożeniem; Nie jestem pewien, czy mój wpis jest ważny.


Wyjaśnienie

Bezwstydnie ukradłem pomysł użycia pojedynczego cudzysłowu do stworzenia pseudo-quinu z wiki> <> i komentarza, który widziałem tutaj raz.

":?!;1-r00gol?!;a0.�
"                     begins string parsing
 :?!;                 terminates program if final character is 0, numerically
     1-               decrements final character by 1
       r              reverses stack
        00g           grabs quotation mark (fancy way of putting " ")
           ol?!;      prints and terminates if stack is empty
                a0.   jumps back to o to loop 

To, co robi, to parsuje wszystko po znaku cudzysłowu jako znaki, a następnie zmniejsza ostatni. Stamtąd odwraca stos (aby drukować we właściwej kolejności), wypycha znak stosu na stos, a następnie drukuje, aż stos będzie pusty.


0

Python, 1 × 10 ^ 194 programów

n=99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
if n:print open(__file__).read().replace(str(n),str(n-1))

To musi być uruchomione z pliku, a nie interaktywnej repliki. To nie jest quine.

Dzięki @The Turtle za pomoc w oszczędzaniu 3 bajtów, czyli więcej miejsca na dziewiątki!
Dzięki @poke za pomoc w oszczędzaniu 2 bajtów, co oznacza więcej miejsca dla dziewiątek!


@ Cheese Lover The if n!=0jest zbędny. Możesz po prostu pisać if n.
Turtle

Możesz także pozbyć się dwóch pól; po if n:i pomiędzy replaceargumentami.
poke

0

Bash, 52 programy

Zupełnie niezainspirowany i (miejmy nadzieję) solidnie na ostatnim miejscu.

echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.