É possível diminuir esse código C? Imprime todos os números primos de 0 a 1000.
C, 89 caracteres
int i,p,c;for(i=2;i<1e3;i++){c=0;for(p=2;p<i;p++)if(i%p==0)c++;if(c==0)printf("%u\n",i);}
É possível diminuir esse código C? Imprime todos os números primos de 0 a 1000.
C, 89 caracteres
int i,p,c;for(i=2;i<1e3;i++){c=0;for(p=2;p<i;p++)if(i%p==0)c++;if(c==0)printf("%u\n",i);}
Respostas:
59 57 bytes
Baseado na solução @feersum, mas a verificação de primalidade pode ser ainda mais aprimorada
for(int p=1,d;d=p++%999;d||printf("%d\n",p))for(;p%d--;);
Editado com base nos comentários de Runer112
d=p++%999
. Caso contrário, isso parece um trabalho de golfe bastante hermético!
(Eu escrevi isso sem perceber as limitações de tamanho em números inteiros em C, portanto, provavelmente não é realmente útil para encurtar o código.)
Primeiro, uma palavra sobre algoritmo. Antes de jogar seu código, você deve pensar na melhor estratégia geral para obter o resultado.
Você está verificando a primalidade fazendo a divisão de teste - testando cada divisor potencial p
de i
. Isso é caro em caracteres, porque são necessários dois loops. Portanto, testar a primalidade sem um loop provavelmente salvará caracteres.
Uma abordagem geralmente mais curta é usar o Teorema de Wilson : o número n
é primo se e somente se
fact(n-1)%n == n-1
Onde fact
é a função fatorial. Desde que você está testando todos os possíveis n
a partir 1
de 1000
, é fácil evitar a implementação factorial, mantendo o controle do produto em execução P
e atualizá-lo por P*=n
após cada loop. Aqui está uma implementação em Python dessa estratégia para imprimir números primos de até um milhão.
Como alternativa, o fato de o seu programa ter apenas até 1000 abre outra estratégia: o teste de primalidade de Fermat . Para alguns a
, todo primo n
satisfaz
pow(a,n-1)%n == 1
Infelizmente, alguns compostos n
também passam neste teste para alguns a
. Estes são chamados pseudoprimes de Fermat . Mas, a=2
e a=3
não falhem juntos até n=1105
, portanto, eles são suficientes para o seu objetivo de verificar os números primos até 1000. (Se 1000 fossem 100, você seria capaz de usar apenas a=2
.) Portanto, verificamos a primalidade com (código não destruído)
pow(2,n-1)%n == 1 and pow(3,n-1)%n == 1
Isso também falha em reconhecer os números primos 2 e 3, portanto esses precisariam ser de caixa especial.
Essas abordagens são mais curtas? Não sei porque não codifico em C. Mas, são idéias que você deve tentar antes de escolher um pedaço de código para começar a identificar caracteres.
int
s são de 32 bits. O mesmo vale para Fermat.
fact(int n, int m) { return (n==0) ? 1 : (n*f(n-1)) % m; }
, o resultado não excederá um número inteiro de 32 bits, mesmo para valores razoavelmente grandes de n
. ( m
é o módulo)
(n*fact(n-1,m)) % m
. O que destaca o problema: você não pode evitar a recursão na implementação de, fact
porque m
será diferente para cada iteração do loop externo.
(Apenas apliquei alguns truques aprendidos em outros idiomas.)
int i=0,p,c;for(;i<1e3;i++){c=0;for(p=2;p<i;)c+=i%p++<1;c||printf("%u\n",i);}
for(int i=0,p,c;i<1e3;i++){c=0;for(p=2;p<i;)c+=i%p++<1;c||printf("%u\n",i);}
Outra reutilização da minha resposta a uma pergunta semelhante .
EDIT : pedaço de código independente, sem função para chamar.
for(int m,n=2;n<999;m>1?m=n%m--?m:n++:printf("%d\n",m=n));
Programa completo:
n=2;main(m){n<999&&main(m<2?printf("%d\n",n),n:n%m?m-1:n++);}
Inspirado na solução da Alchymist:
int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}