¿Es posible hacer este código C más pequeño? Imprime todos los 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);}
¿Es posible hacer este código C más pequeño? Imprime todos los 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);}
Respuestas:
59 57 bytes
Basado en la solución @feersum, pero el control de primalidad puede ser más avanzado
for(int p=1,d;d=p++%999;d||printf("%d\n",p))for(;p%d--;);
Editado en base a los comentarios de Runer112
d=p++%999
. De lo contrario, ¡esto parece un trabajo de golf bastante hermético!
(Escribí esto sin darme cuenta de las limitaciones de tamaño en los enteros en C, por lo que probablemente no sea realmente útil para acortar el código).
Primero, una palabra sobre algoritmo. Antes de jugar golf su código, debe pensar en la mejor estrategia general para obtener el resultado.
Estás verificando la primalidad haciendo una división de prueba, probando cada divisor potencial p
de i
. Eso es costoso en los personajes porque requiere dos bucles. Por lo tanto, probar la primalidad sin un bucle probablemente ahorrará caracteres.
Un enfoque a menudo más corto es usar el Teorema de Wilson : el número n
es primo si y solo si
fact(n-1)%n == n-1
¿Dónde fact
está la función factorial? Como está probando todo lo posible n
desde el 1
principio 1000
, es fácil evitar implementar factorial al realizar un seguimiento del producto en ejecución P
y actualizarlo P*=n
después de cada ciclo. Aquí hay una implementación de Python de esta estrategia para imprimir primos de hasta un millón.
Alternativamente, el hecho de que su programa solo tenga que ser hasta 1000 abre otra estrategia: la prueba de primalidad de Fermat . Para algunos a
, cada primo n
satisface
pow(a,n-1)%n == 1
Desafortunadamente, algunos compuestos n
también pasan esta prueba para algunos a
. Estos se llaman pseudoprimos de Fermat . Pero, a=2
y a=3
no fracasen juntos hasta n=1105
, por lo que son suficientes para su propósito de verificar números primos hasta 1000. (Si 1000 en lugar de 100, solo podría usarlo a=2
). Entonces, verificamos la primalidad con (código no protegido)
pow(2,n-1)%n == 1 and pow(3,n-1)%n == 1
Esto tampoco reconoce los números primos 2 y 3, por lo que estos deberían estar en mayúsculas especiales.
¿Son estos enfoques más cortos? No lo sé porque no codifico en C. Pero, son ideas que debes probar antes de decidirte por un código para comenzar a escribir caracteres.
int
s son de 32 bits. Lo mismo va para Fermat's.
fact(int n, int m) { return (n==0) ? 1 : (n*f(n-1)) % m; }
, el resultado no desbordará un entero de 32 bits incluso para valores bastante grandes de n
. ( m
es el módulo)
(n*fact(n-1,m)) % m
. Lo que resalta el problema: no puede evitar la recurrencia en la implementación de fact
porque m
será diferente para cada iteración del bucle externo.
(Solo apliqué algunos trucos aprendidos en otros 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);}
Otra reutilización de mi respuesta a una pregunta similar .
EDITAR : pieza de código independiente, no hay función para llamar.
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 por la solución de Alchymist:
int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}