Програма, яка друкує програми


13

Виклик

Ваша мета - написати програму, яка друкує іншу програму. Ця надрукована програма повинна друкувати іншу програму, а нова програма повинна друкувати іншу програму до кінця.

Правила

  1. Кожна програма повинна мати менше 256 байт. (Якщо це потрібно змінити, залиште коментар)
  2. Остання програма повинна бути порожньою програмою.
  3. Повинна бути обмежена кількість програм, тому програма не може бути королевою.
  4. Усі програми повинні працювати однаковою мовою.
  5. Вхід заборонено.
  6. Переможна програма - це програма, яка друкує якомога більше програм, рахуючи себе.

Щасти!


Максимальний бал - 2^2048або 3.2317e616.
orlp

Щоб полегшити порівняння великих балів, будь-ласка, додайте наближення до балу у формі, a*10^bде 1<=a<10і bце натуральне число.
недолік

2
Власне, мій попередній розрахунок був неправильним. Припустимо, що програма повинна бути в байтах, максимально можливий бал <кількість занадто довге для коментарів> або 1.2673e614.
orlp

Відповіді:


20

CJam, 4,56 × 10 526 програм

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`}?\"_~"}_~

Точний рахунок: 254 219 + 254 192 + 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 3

Усі програми повинні бути збережені за допомогою кодування ISO-8859-1, щоб відповідати обмеженню розміру файлу.

Дякуємо @ChrisDrost, який вказав на помилку та запропонував підхід.

Спробуйте його в Інтернеті в інтерпретаторі CJam .

254 219 + 2 ≈ 4,56 × 10 526 програм

Рядку частку балу можна досягти за допомогою наступної, набагато простішої програми 1 .

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

Запуск цієї програми виробляє програму

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

і після 254 219 - ще 1 ітерація, програма

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

Ця остання непуста програма виходить із помилкою 2 і нічого не друкує (порожня програма).

Як це працює

Припустимо, рядок вже є в стеці.

{      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 більше програм

Тут дещо з глузду стає щось.

Перша програма дуже стислива. Написавши подібну програму, яка замість порожньої програми, врешті-решт, виробляє першу програму з вищевказаного розділу, ми можемо покращити показник на 254 192 програми 3 .

Програма

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

схожа на першу програму попереднього розділу, а запуск першого та його вихід для 254 192 ітерацій створює другий.

Припустимо, рядок вже є в стеку:

{                           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.

Програми Moar

Перша програма попереднього розділу все ще сильно стискається, тому ми можемо застосувати аналогічний метод і написати програму, яка після 254 166 ітерацій виробляє вищезгадану програму.

Повторюючи цю техніку знову і знову, поки ми не досягнемо межі 255 байт, ми можемо додати 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 1 ≈ 1,59 × 10 399 програм до ті з попередніх розділів.


1 Новий рядок додано для наочності.
2 За консенсусом щодо Meta це дозволено за замовчуванням.
3 або 0,00000000000000000000000000000000000000000000000000000000000000000012%



5

JavaScript, 1000 програм

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)
      : ``
)

Чи справедливо це, залежить саме від того, як зрозуміти третє правило.


Це не технічно Куайн, так як він друкує модифіковану версію свого власного вихідного коду , а не ідентичну копію. Він, очевидно, використовує хіно-подібні методи. Я думаю, нам буде потрібно роз'яснення від @TheTurtle.
JohnE

5
@JohnE та Ypnypn Це щось подібне, що я задумав. Це працює.
Черепаха

6
Ви все ще знаходитесь набагато нижче межі довжини коду. Чому б ти не змінити 999 на щось більше?
DankMemes

4

Ruby, 1.628 × 10 ^ 237 програм

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

Той самий підхід, що і в моїй відповіді Perl, але оскільки Рубі вже обробляє великі дані, її простіше зберігати як шестигранну.


Ruby, 9,277 × 10 ^ 90 програм

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

Тож ця спроба є дещо іншою мірою на попередньому квіноподібному, але через всі додаткові функції я не отримую, щоб число десь було ближче, ніж інше ... Було цікаво спробувати інший підхід, хоча!



2

C, 2,2 * 10 ^ 177 програм

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

Це не ідеально, але досить добре. Я маю на увазі, що це точно 255байти і створює програми однакової довжини. Ви, напевно, могли би заграти ще трохи, щоб отримати ще кілька програм, але я залишу це як зараз.

Програма заснована на простому C quine. Крім того, існує досить простий алгоритм підрахунку, який підраховує всі можливі значення масиву char n. У нас стільки програм, скільки перестановок рядка n.

Діапазон значень обмежений діапазоном від #(= 35) до [= (91). Це тому, що я не хочу ні в рядку, "ні \в їх рядок, тому що їх потрібно уникати.

Генерація програми закінчується, коли всі значення в масиві char nє [. Потім вона виводить просту манекенську програму main(){}, яка сама нічого не видає.

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

Як демонстрація того, що це має працювати, я просто змінив обмеження, тому використовуються лише символи між ASCII-кодом 35і 36використовуються лише 4 елементи масиву.

Отримані в результаті програми є

% 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(){})

Це виводить 2^4 + 1 = 17різні програми.

Таким чином, програма, викладена вище, виводить ((91-35)+1)^101 + 1 = 57^101 + 1 ~= 2.2 * 10^177різні програми. Я не цілком впевнений, чи зараховується це чи чи мій розрахунок навіть правильний


1
Чи можете ви включити, що мова йде про 2.2 * 10^177(для тих, хто хоче порівняти)?
flawr

Не знав, як обчислити це, але я включив його ;-)
MarcDefiant


1

Perl, 1 × 10 ^ 163

В іншому випадку це досить основна квітка, скорочена до якомога менше знаків, що працює лише в той час, як лічильник не є 0.

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

1

Ліпп звичайний, 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#)))))
  • Є 113 дев'яток.
  • У наступній програмі 112 дев'яток, а за ними 8
  • У наступній програмі 112 дев'яток, а за ними 7
  • ...

Кількість дев'яти обмежена максимальним розміром коду, 256 з урахуванням пробілів, введених принтером.


1

Perl, 1,4 * 10 ^ 225

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

Аналогічний підхід до пітона; такий же результат!


0

> <> , 65534 (?) Програми

Я додав знак питання поруч із 65533, оскільки я ще не переконався, що він може надрукувати 65533 (хоча я маю підстави вважати, що так слід). Як тільки у мене з’явиться трохи більше часу, я збираюсь випробувати спосіб його тестування.

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

Ви можете спробувати онлайн тут .

Суть цієї програми полягає в тому, що вона змінює вихідний знак символу в самому кінці, а потім зменшує його числове значення перед друком. Я отримав 65534 програми, тому що значення символу ascii в кінці коду дорівнює 65533, тому для підрахунку першої програми ми маємо 65534 (якщо вважати порожню програму 65535, я думаю). Остання програма «повернулася» - це нічого; воно просто закінчується, коли значення символу дорівнює 0.

Я впевнений, що він зможе надрукувати символ для всіх ітерацій: я не зміг знайти остаточне джерело, скільки символів може надрукувати, але знаки є безпосередньо під 65533, чисельно.

Повідомте мене, чи є проблеми з цією реалізацією; Я трохи не впевнений у дійсності свого вступу.


Пояснення

Я безсоромно вкрав ідею використання єдиного лапки для створення псевдокіни з вікі> <> та коментаря, якого я тут бачив одного разу.

":?!;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 

Що робити, це проаналізувати все після лапки як символи, а потім зменшити останню. Звідти він просто перевертає стек (щоб друкувати в потрібному порядку), натискає лапки на стек, а потім друкує, поки стек не порожній.


0

Python, 1 × 10 ^ 194 програми

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

Це потрібно запустити з файлу, а не інтерактивного відбору. Це не королева.

Завдяки @The Turtle допомогла мені зберегти 3 байти, що більше місця для дев’яти!
Завдяки @poke за допомогу мені зберегти 2 байти, що більше місця для дев’яти!


@ Любитель сиру - if n!=0це зайве. Можна просто написати if n.
Черепаха

Ви можете позбутися і двох просторів; після аргументів if n:та між ними replace.
ткнути

0

Баш, 52 програми

Цілком натхненно, і (сподіваємось) твердо на останньому місці.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.