Tutti i numeri primi da 0 a 1000


9

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

6
Giusto per anticipare alcuni downvotes "Non vogliamo sfide specifiche della lingua", chiedere aiuto per giocare a golf un po 'di codice è un argomento e una storia diversa rispetto alle sfide.
Martin Ender,

4
Dobbiamo preservare l'algoritmo o solo il risultato finale?
John Dvorak,

Comincerei io a 2 per essere rigorosamente preciso, poiché questo stampa 0 e 1.
istocratico

stai cercando di rendere il codice più veloce o stai cercando di usare meno caratteri nel codice sorgente?
user3629249

1
Dato che stai chiedendo assistenza per il golf, sarebbe utile includere nel post il conteggio dei personaggi della tua soluzione attuale (lo faccio come 89).
Mark Reed,

Risposte:


7

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


2
Il controllo può essere legato giocato a golf un po 'di più: d=p++%999. Altrimenti, questo sembra un lavoro da golf piuttosto ermetico!
Runer112,

10

67 byte

In C non esiste una vera alternativa alla divisione di prova, ma può certamente essere un po 'golfato.

for(int p=1,d;p++<999;d&&printf("%d\n",p))for(d=p;--d>1;)d=p%d?d:1;

Richiede dichiarazioni iniziali C99, che salvano 1 byte.


6

(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 pdi 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'è factla funzione fattoriale. Dal momento che stai testando tutto il possibile nda 1a 1000, è facile evitare l'implementazione fattoriale tenendo traccia del prodotto in esecuzione Pe aggiornandolo P*=ndopo 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 nsoddisfa

pow(a,n-1)%n == 1

Sfortunatamente, alcuni composti nsuperano anche questo test per alcuni a. Questi sono chiamati pseudoprimi di Fermat . Ma, a=2e a=3non 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.


1
Il teorema di Wilson non è utile in C perché i ints sono a 32 bit. Lo stesso vale per Fermat.
feersum

@feersum Oh, spara. Questo è un problema anche per i fattoriali. Esiste un tipo big-int?
xnor

@xnor Non integrato.
Martin Ender,

1
se uno lo definisce, 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)
apnorton

@anorton Penso che intendi (n*fact(n-1,m)) % m. Il che evidenzia il problema: non è possibile evitare la ricorsione nell'implementazione di factperché msarà diverso per ogni iterazione del ciclo esterno.
hvd,

4

78 77 caratteri

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

76 caratteri in modalità C99

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

2

58 caratteri (o 61 per un programma completo)

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

1

67 64 byte

Ispirato alla soluzione di Alchymist:

int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.