Verificador principal de autolimpeza

8

Vamos direto ao assunto. Seu desafio é criar um programa que faça essas coisas, dependendo de sua entrada:

  1. Se a entrada for um número, imprima "Prime" se o número for um número primo e "Not prime" se o número não for um número primo. Você pode assumir que o número é> 1.

  2. Se a entrada for dois números, imprima todos os números primos entre o primeiro número (inclusive) e o segundo número (exclusivo). Você pode assumir que o primeiro número é menor que o segundo.

  3. Aí vem o verdadeiro desafio: se não houver entrada, o programa deve produzir uma versão mais curta de si mesma que faz exatamente as mesmas coisas que o programa original. O programa não tem permissão para ler de nenhum arquivo ou da web. O novo programa também deve ser capaz de fazer isso. Deve funcionar por pelo menos 5 gerações. O novo programa não precisa estar no mesmo idioma que o primeiro.

Pontuação:

Sua pontuação é igual à soma do número de bytes nas cinco primeiras gerações de seu envio (o envio em si é a geração um). Se o novo código estiver codificado no primeiro programa, multiplique a pontuação por 1,5. Menor pontuação ganha. (Se você encontrar algum tipo de falha no sistema de pontuação, informe-me nos comentários)

Loovjo
fonte
1
Você deve especificar condições para a parte do quine: o programa pode ler seu próprio código-fonte, etc. Veja esta pergunta de 5 dias atrás em nosso meta site: meta.codegolf.stackexchange.com/q/4877/15599
Level River St
Acho que minhas edições abordam todos, exceto um dos comentários anteriores. O único problema remanescente: o que conta como codificação embutida?
Rainbolt 17/03/2015
Eu acho que esse é um [código-golfe] ("o código mais curto vence" em algumas métricas), não precisa ser um [código-desafio].
Kennytm 17/03/2015
Que tal "Gerador de programa principal" , "Produzir cinco gerações de números primos" ou "Gerador de pseudo-quino primário" ?
Rainbolt 17/03/2015

Respostas:

10

CJam, 66 + 65 + 64 + 63 + 62 = 320 325 355 bytes

As 5 linhas a seguir são as primeiras 5 gerações:

{     `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~
{    `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~
{   `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~
{  `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~
{ `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~

O último produz

{`(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~

que ainda executa as tarefas principais corretamente.

Teste aqui.

Explicação

A solução CJam básica é

{"_~"}_~

que pode ser estendido com muita facilidade a uma solução generalizada. Para uma explicação disso, veja minha resposta aqui .

As idéias básicas para esta resposta são:

  • Inicie o quine com vários espaços e remova um deles ao fazer o quine.
  • Obtenha uma matriz com todos os números de entrada (0, 1 ou 2) e escolha algum código para executar, dependendo do comprimento (usando-o para indexar em uma matriz).

Aqui está um detalhamento do código dentro do quine:

"Remove a space from the block's string representation:";
`(\1>+
`      "Get the string representation of the block.";
 (\    "Slice off the leading '{' and pull the remaining string back up.";
   1>  "Remove the first character, i.e. a space.";
     + "Prepend the '{' to the string again.";

"Get the array of inputs and choose the code:";
q~](\_,[...]=~
q~             "Read and eval the input.";
  ]            "Wrap everything (including the string for the block) in an array.";
   (\          "Shift off the string and swap it with the rest of the array.";
     _,        "Duplicate the input array and get its length.";
       [...]=  "Use it to index into this array.";
             ~ "If there are no inputs there will now be an array on the top of the
                stack, which ~ will unwrap. Otherwise there will be a block which ~
                will evaluate.";

"If there is no input, push the string needed for the quine and put it in
 an array for ~ to unwrap:";
"_~"a

"If there is one input, test for primality:";
~mp'P"Not p"?"rime"@;
~mp                   "Unwrap the input array and test for primality.";
   'P"Not p"?         "Choose either 'P' or 'Not p' depending on the result.";
             "rime"   "Push the common part of the string.";
                   @; "Pull up the quine string and discard it.";

"If there are two inputs, print an array with all the primes in the range:";
~,>{mp},p;
~          "Unwrap the array leaving N and M on the stack.";
 ,         "Get a range [0 1 .. N-1].";
  >        "Drop the first M elements, giving [M M+1 .. N-1].";
   {mp},   "Filter to keep only the primes.";
        p  "Pretty-print the array.";
         ; "Discard the quine string.";
Martin Ender
fonte
Você poderia adicionar uma explicação?
Loovjo 17/03/2015
1
@ Loovjo Sim, eu irei, mas não antes de terminar o golfe. ;)
Martin Ender
Você poderia colocar os programas em diferentes blocos de código? Meio que me confundiu quando li pela primeira vez.
Loovjo 17/03/2015
O @Loovjo esclareceu que são 5 programas e acrescentou uma explicação completa #
Martin Ender
6

C, Pontuação: 553 + 552 + 551 + 550 + 549 = 2755,

Comprimento original: 553, Avg: 551

EDIT: Apenas 5 gerações, não 6!

Parece que Martin me venceu no tempo e no placar (quase em uma ordem de magnitude!). Ah bem.

O programa original é o seguinte:

char*c="char*c=%c%s%c;k=%d,a;p(c,v,d){for(v=2;v<c;v++)d+=!(c%cv);return!d;}int main(int C,char**V){if(C==1){printf(c,34,c,34,k/10,37,34,34,34,34,34,37,34);return 0;}a=atoi(V[1]);if(C==2)printf(p(a,0,0)?%cPrime%c:%cNot prime%c);if(C==3)for(;a<atoi(V[2]);a++)if(p(a,0,0))printf(%c%cd %c,a);}";k=10000,a;p(c,v,d){for(v=2;v<c;v++)d+=!(c%v);return!d;}int main(int C,char**V){if(C==1){printf(c,34,c,34,k/10,37,34,34,34,34,34,37,34);return 0;}a=atoi(V[1]);if(C==2)printf(p(a,0,0)?"Prime":"Not prime");if(C==3)for(;a<atoi(V[2]);a++)if(p(a,0,0))printf("%d ",a);}

Vou desvendá-lo um pouco para melhor compreensão, mas para que funcione corretamente, as novas linhas NÃO fazem parte do programa.

char*c="char*c=%c%s%c;k=%d,a;p(c,v,d){for(v=2;v<c;v++)d+=!(c%cv);return!d;}int main(int C,char**V){if(C==1){printf(c,34,c,34,k/10,37,34,34,34,34,34,37,34);return 0;}a=atoi(V[1]);if(C==2)printf(p(a,0,0)?%cPrime%c:%cNot prime%c);if(C==3)for(;a<atoi(V[2]);a++)if(p(a,0,0))printf(%c%cd %c,a);}";
k=10000,a;
p(c,v,d){
    for(v=2;v<c;v++)
        d+=!(c%v);
    return!d;
}
int main(int C,char**V){
    if(C==1){
        printf(c,34,c,34,k/10,37,34,34,34,34,34,37,34);
        return 0;
    }
    a=atoi(V[1]);
    if(C==2)
        printf(p(a,0,0)?"Prime":"Not prime");
    if(C==3)
        for(;a<atoi(V[2]);a++)
            if(p(a,0,0))
                printf("%d ",a);
}

A única coisa que muda de programa para programa é o valor de k, que perde exatamente um dígito a cada iteração. Curiosamente, após a 5ª geração, k se torna zero e permanece lá, para que você possa iterar ad infinitum e sempre ter saída válida.

BrainSteel
fonte
2

Tcl 253 + 252 + 251 + 250 + 249 = 1255 bytes

eval [set x {     proc q a\ b {incr b;expr $a%$b?\[q $a $b]:$a==$b}
proc 1 a {if [q $a 1] puts\ Prime {puts Not\ Prime}}
proc 2 a\ b {while $b-\$a {if [q $a 1] puts\ $a;incr a}}
proc 0 {} {puts "eval \[set x {[string ra $::x 1 end]}]"}
$argc {*}$argv}]

O código precisa terminar com uma nova linha. Explicação:

eval [set x {...}]

Escreva o código em x e execute-o.

$argc {*}$argv

Execute o comando cujo nome é o comprimento do argumento, passando os argumentos adiante.

proc q a\ b {incr b;expr $a%$b?\[q $a $b]:$a==$b}

Retorna 1 quando a é primo, 0 mais. Usa recursão; a segunda barra invertida impede a substituição de comandos do intérprete e ativa o de expr(que é preguiçoso).

proc 1 a {if [q $a 1] puts\ Prime {puts Not\ Prime}}
proc 2 a\ b {while $b-\$a {if [q $a 1] puts\ $a;incr a}}

Implementação direta dos requisitos.

proc 0 {} {puts "eval \[set x {[string ra $::x 1 end]}]"}

Esta é a solução, removendo um espaço desde o início de cada vez.

Philipp
fonte
"Sua pontuação é igual à soma do número de bytes nas cinco primeiras gerações de seu envio (o envio em si é a geração um)."
Martin Ender