È possibile ridurre questo codice C? Stampa tutti i numeri primi da 0 a 1000.
C, 89 caratteri
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);}
È possibile ridurre questo codice C? Stampa tutti i numeri primi da 0 a 1000.
C, 89 caratteri
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);}
Risposte:
59 57 byte
Basato sulla soluzione @feersum ma il controllo della primalità può essere ulteriormente approfondito
for(int p=1,d;d=p++%999;d||printf("%d\n",p))for(;p%d--;);
Modificato in base ai commenti di Runer112
d=p++%999
. Altrimenti, questo sembra un lavoro da golf piuttosto ermetico!
(Ho scritto questo senza rendersi conto delle limitazioni di dimensione sugli interi in C, quindi probabilmente non è effettivamente utile per abbreviare il codice.)
Innanzitutto, una parola sull'algoritmo. Prima di giocare a golf con il codice, dovresti pensare alla migliore strategia generale per ottenere il risultato.
Stai verificando la primalità facendo la divisione di prova - testando ogni potenziale divisore p
di i
. È costoso nei personaggi perché ci vogliono due anelli. Quindi, testare la primalità senza un loop probabilmente salverà i personaggi.
Un approccio spesso più breve è quello di usare il Teorema di Wilson : il numero n
è primo se e solo se
fact(n-1)%n == n-1
dov'è fact
la funzione fattoriale. Dal momento che stai testando tutto il possibile n
da 1
a 1000
, è facile evitare l'implementazione fattoriale tenendo traccia del prodotto in esecuzione P
e aggiornandolo P*=n
dopo ogni ciclo. Ecco un'implementazione Python di questa strategia per stampare numeri primi fino a un milione.
In alternativa, il fatto che il tuo programma debba essere solo fino a 1000 apre un'altra strategia: il test di primalità Fermat . Per alcuni a
, ogni numero primo n
soddisfa
pow(a,n-1)%n == 1
Sfortunatamente, alcuni composti n
superano anche questo test per alcuni a
. Questi sono chiamati pseudoprimi di Fermat . Ma, a=2
e a=3
non fallire insieme fino a quando n=1105
, quindi sono sufficienti per il tuo scopo di controllare i numeri primi fino a 1000. (Se 1000 fossero invece 100, saresti in grado di usare solo a=2
.) Quindi, controlliamo la primalità con (codice non golfizzato)
pow(2,n-1)%n == 1 and pow(3,n-1)%n == 1
Anche questo non riesce a riconoscere i numeri primi 2 e 3, quindi quelli dovrebbero essere sottoposti a casi speciali.
Questi approcci sono più brevi? Non lo so perché non scrivo codice in C. Ma sono idee che dovresti provare prima di accontentarti di un pezzo di codice per iniziare a eliminare i caratteri.
int
s sono a 32 bit. Lo stesso vale per Fermat.
fact(int n, int m) { return (n==0) ? 1 : (n*f(n-1)) % m; }
il risultato non supererà un numero intero a 32 bit per valori anche abbastanza grandi di n
. ( m
è il modulo)
(n*fact(n-1,m)) % m
. Il che evidenzia il problema: non è possibile evitare la ricorsione nell'implementazione di fact
perché m
sarà diverso per ogni iterazione del ciclo esterno.
(Ho appena applicato alcuni trucchi appresi in altre lingue.)
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);}
Un altro riutilizzo della mia risposta a una domanda simile .
EDIT : codice autonomo, nessuna funzione da chiamare.
for(int m,n=2;n<999;m>1?m=n%m--?m:n++:printf("%d\n",m=n));
Programma completo:
n=2;main(m){n<999&&main(m<2?printf("%d\n",n),n:n%m?m-1:n++);}
Ispirato alla soluzione di Alchymist:
int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}