Um programa que imprime programas

13

Desafio

Seu objetivo é escrever um programa que imprima outro programa. Esse programa impresso deve imprimir outro programa e o novo programa deve imprimir outro programa, até o final.

Regras

  1. Cada programa deve ter menos de 256 bytes. (Se isso precisar ser alterado, deixe um comentário)
  2. O último programa deve ser um programa vazio.
  3. Deve haver um número finito de programas, para que o programa não possa ser um problema.
  4. Todos os programas devem ser executados no mesmo idioma.
  5. Nenhuma entrada é permitida.
  6. O programa vencedor é o programa que imprime o maior número possível de programas, contando-se.

Boa sorte!

A tartaruga
fonte
A pontuação máxima é 2^2048, ou 3.2317e616.
orlp 10/09/15
Para facilitar a comparação de grandes pontuações, inclua uma aproximação à sua pontuação no formato a*10^bonde 1<=a<10e bé um número natural.
flawr
2
Na verdade, meu cálculo anterior estava errado. Supondo que o programa deva estar em bytes, a pontuação máxima possível é <número muito longo para comentários> ou 1.2673e614.
orlp 10/09/2015

Respostas:

20

CJam, 4,56 × 10 526 programas

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

Escore exato: 254 219 + 254 192 + 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 3

Todos os programas precisam ser salvos usando a codificação ISO-8859-1 para atender ao limite de tamanho do arquivo.

Obrigado a @ChrisDrost, que apontou um erro e sugeriu a abordagem de aninhamento.

Experimente on-line no intérprete CJam .

254 219 + 2 × 4,56 × 10 526 programas

O compartilhamento de linha da pontuação pode ser alcançado pelo seguinte programa muito mais simples 1 .

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

A execução deste programa produz o programa

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

e após 254 219 - mais 1 iterações, o programa

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

Este último programa não vazio sai com um erro 2 e não imprime nada (o programa vazio).

Como funciona

Suponha que a string já esteja na pilha.

{      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 mais programas

É aqui que as coisas ficam um pouco loucas.

O primeiro programa é altamente compressível. Ao escrever um programa semelhante que, em vez do programa vazio, eventualmente produz o primeiro programa da seção acima, podemos melhorar a pontuação em 254 192 programas 3 .

O programa

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

é semelhante ao primeiro programa da seção anterior e a execução do primeiro e sua saída para 254 192 iterações produz o último.

Suponha que a string já esteja na pilha:

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

Programas Moar

O primeiro programa da seção anterior ainda é altamente compressível; portanto, podemos aplicar um método semelhante e escrever um programa que, após 254 166 iterações, produza o programa mencionado acima.

Repetindo essa técnica várias vezes até atingirmos o limite de 255 bytes, podemos adicionar um total de 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 1 ≈ 1,59 × 10 399 programas para os das seções anteriores.


1 Nova linha adicionada para maior clareza.
2 Por consenso no Meta , isso é permitido por padrão.
3 ou 0.00000000000000000000000000000000000000000000000000000000000000000012%

Dennis
fonte
5

JavaScript, 1000 programas

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

Se isso é válido depende exatamente de como entender a terceira regra.

Ypnypn
fonte
Tecnicamente, não é um problema, pois imprime uma versão modificada de seu próprio código-fonte, em vez de uma cópia idêntica. Ele usa técnicas semelhantes a quine, obviamente. Acho que precisaremos de esclarecimentos do @TheTurtle.
Johne
5
@ JohnE e Ypnypn Isso é algo que eu imaginava. Isso funciona.
The Turtle
6
Você ainda está bem abaixo do limite de tamanho do código. Por que você não muda 999 para algo maior?
DankMemes
4

Ruby, 1.628 × 10 ^ 237 programas

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

A mesma abordagem da minha resposta Perl, mas como o Ruby já lida com grandes ints, é mais fácil armazenar como hexadecimal.


Ruby, 9.277 × 10 ^ 90 programas

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

Portanto, essa tentativa é uma variação ligeiramente diferente da anterior, mas por causa de todas as funções extras, não estou conseguindo o número tão alto quanto o outro ... Foi interessante tentar outra abordagem!

Dom Hastings
fonte
4

Programas Python 2, 9,7 * 10 ^ 229

O=0
if len(hex(O))<191:print"O=0x%x"%(O+1)+open(__file__).read()[-68:]
Azul
fonte
Bom, não pensei em repetição de cordas!
Dom Hastings
2

C, 2,2 * 10 ^ 177 programas

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

Não é perfeito, mas muito bom. Quero dizer, é exatamente 255bytes de comprimento e gera programas do mesmo comprimento. Você provavelmente poderia mexer um pouco mais para ganhar mais alguns programas, mas vou deixar como está por enquanto.

O programa é baseado em uma simples coluna C. Além disso, existe um algoritmo de contagem bastante simples que conta com todos os valores possíveis da matriz char n. Temos tantos programas quanto permutações da string n.

O intervalo de caracteres é limitado a um intervalo de #(= 35) a [= (91). Isso porque eu não quero nenhum "ou \na cadeia, porque eles precisam ser escapados.

A geração do programa termina quando todos os valores na matriz char nsão [. Em seguida, ele gera um programa fictício simples main(){}, que por si só não gera nada.

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

Como demonstração de que deveria funcionar, mudei os limites, apenas caracteres entre o Código ASCII 35e 36são usados ​​e apenas 4 elementos de matriz.

Os programas resultantes são

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

Isso gera 2^4 + 1 = 17diferentes programas.

Portanto, o programa acima gera ((91-35)+1)^101 + 1 = 57^101 + 1 ~= 2.2 * 10^177diferentes programas. Não tenho muita certeza se isso conta ou se meu cálculo está correto

MarcDefiant
fonte
1
Você poderia incluir que se trata 2.2 * 10^177(para aqueles que querem comparar)?
flawr
Não sabia como calcular um presente, mas eu incluí-lo ;-)
MarcDefiant
wolframalpha.com =)
flawr
1

Perl, 1 × 10 ^ 163

Caso contrário, este é um quine bastante básico, reduzido ao mínimo de caracteres possível, que só funciona enquanto o contador não estiver 0.

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

Lisp comum, 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#)))))
  • Existem 113 noves.
  • O próximo programa tem 112 noves, seguido por 8
  • O próximo programa tem 112 noves, seguido por 7
  • ...

O número de noves é limitado pelo tamanho máximo do código, 256, levando em consideração os espaços introduzidos pela impressora.

coredump
fonte
1

Perl, 1,4 * 10 ^ 225

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

Abordagem semelhante ao python; mesmo resultado!

alexander-brett
fonte
0

> 65534 (?) Programas

Adicionei um ponto de interrogação ao lado de 65533, pois ainda tenho que verificar se ele pode imprimir 65533 (embora eu tenha motivos para acreditar que deveria). Quando tiver um pouco mais de tempo, vou descobrir uma maneira de testá-lo.

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

Você pode experimentá-lo online aqui .

A essência deste programa é que ele altera a saída do caractere no final e diminui seu valor numérico antes da impressão. Eu tenho 65534 programas porque o valor ascii do caractere no final do código é 65533, então contando o primeiro programa que temos 65534 (se você contar o programa vazio 65535, eu acho). O último programa "retornado" não é nada; simplesmente termina quando o valor do caractere é 0.

Tenho certeza de que ele poderá imprimir um caractere para todas as iterações: não consegui encontrar uma fonte definitiva para quantos caracteres> <> podem imprimir, mas existem caracteres diretamente abaixo de 65533, numericamente.

Deixe-me saber se há algum problema com esta implementação; Estou um pouco inseguro sobre a validade da minha inscrição.


Explicação

Eu descaradamente roubei a idéia de usar aspas simples para criar uma pseudoquina no wiki> <> e um comentário que vi aqui uma vez.

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

O que ele faz é analisar tudo após as aspas como caracteres e, em seguida, diminuir o último. A partir daí, apenas inverte a pilha (para imprimir na ordem correta), coloca aspas na pilha e depois imprime até que a pilha esteja vazia.

Cole
fonte
0

Python, 1 × 10 ^ 194 programas

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

Isso deve ser executado a partir de um arquivo, não de uma substituição interativa. Não é um problema.

Agradeço à @The Turtle por me ajudar a economizar 3 bytes, que é mais espaço para noves!
Agradeço ao @poke por me ajudar a economizar 2 bytes, o que é mais espaço para noves!

Amante de Queijo
fonte
@ Amante de queijo O if n!=0é redundante. Você pode apenas escrever if n.
The Turtle
Você pode se livrar de dois espaços também; depois dos if n:e entre os replaceargumentos.
cutuca
0

Bash, 52 programas

Totalmente sem inspiração e (esperançosamente) solidamente em último lugar.

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
Chris
fonte