Tous les nombres premiers de 0 à 1000

9

Est-il possible de rendre ce code C plus petit? Il imprime tous les nombres premiers de 0 à 1000.

C, 89 caractères

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);}
Jonas Grunau
la source
6
Juste pour anticiper certains votes négatifs "Nous ne voulons pas de défis spécifiques à la langue", demander de l'aide pour jouer au code est un sujet et une histoire différente de celle des défis.
Martin Ender
4
Faut-il conserver l'algorithme, ou seulement le résultat final?
John Dvorak
Je commencerais i à 2 pour être strictement précis, car cela
affiche
essayez-vous d'accélérer l'exécution du code ou d'essayer d'utiliser moins de caractères dans le code source?
user3629249
1
Puisque vous demandez de l'aide pour le golf, il serait utile d'inclure le nombre de caractères de votre solution actuelle dans votre message (je le fais comme 89).
Mark Reed

Réponses:

7

59 57 octets

Basé sur la solution @feersum mais le contrôle de primalité peut être approfondi

for(int p=1,d;d=p++%999;d||printf("%d\n",p))for(;p%d--;);

Modifié sur la base des commentaires de Runer112

Alchymiste
la source
2
Le contrôle lié peut être golfed un peu plus: d=p++%999. Sinon, cela semble être un travail de golf assez hermétique!
Runer112
10

67 octets

En C, il n'y a pas de véritable alternative à la division d'essai, mais elle peut certainement être un peu jouée au golf.

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

Nécessite des déclarations initiales C99, ce qui économise 1 octet.

feersum
la source
6

(J'ai écrit ceci sans réaliser les limitations de taille sur les entiers en C, donc ce n'est probablement pas vraiment utile pour raccourcir le code.)

Tout d'abord, un mot sur l'algorithme. Avant de jouer à votre code, vous devez réfléchir à la meilleure stratégie globale pour obtenir le résultat.

Vous vérifiez la primauté en effectuant la division d'essai - en testant chaque diviseur potentiel pde i. C'est coûteux en caractères car cela prend deux boucles. Ainsi, tester la primalité sans boucle est susceptible de sauver des caractères.

Une approche souvent plus courte consiste à utiliser le théorème de Wilson : le nombre nest premier si et seulement si

fact(n-1)%n == n-1

factest la fonction factorielle. Puisque vous testez tout le possible nde 1à 1000, il est facile d'éviter d'implémenter le factoriel en gardant une trace du produit en cours d'exécution Pet en le mettant à jour P*=naprès chaque boucle. Voici une implémentation Python de cette stratégie pour imprimer des nombres premiers jusqu'à un million.

Alternativement, le fait que votre programme ne doive être que jusqu'à 1000 ouvre une autre stratégie: le test de primalité Fermat . Pour certains a, chaque prime nsatisfait

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

Malheureusement, certains composites nréussissent également ce test pour certains a. Celles-ci sont appelées pseudoprimes Fermat . Mais, a=2et a=3n'échouent pas ensemble avant n=1105, ils suffisent donc pour vérifier les nombres premiers jusqu'à 1000. (Si 1000 était au lieu de 100, vous ne pourriez utiliser que a=2.) Donc, nous vérifions la primauté avec (code non golfé)

pow(2,n-1)%n == 1 and pow(3,n-1)%n == 1

Cela ne reconnaît pas non plus les nombres premiers 2 et 3, donc ceux-ci devraient être placés dans un boîtier spécial.

Ces approches sont-elles plus courtes? Je ne sais pas parce que je ne code pas en C. Mais, ce sont des idées que vous devriez essayer avant de vous installer sur un morceau de code pour commencer à sortir les personnages.

xnor
la source
1
Le théorème de Wilson n'est pas utile en C car les ints sont 32 bits. Il en va de même pour Fermat.
feersum
@feersum Oh, tire. C'est aussi un problème pour les factorielles. Existe-t-il un type big-int?
xnor
@xnor Non intégré.
Martin Ender
1
si l'on définit fact(int n, int m) { return (n==0) ? 1 : (n*f(n-1)) % m; }alors le résultat ne dépassera pas un entier 32 bits pour des valeurs même assez grandes de n. ( mest le module)
apnorton
@anorton Je pense que tu veux dire (n*fact(n-1,m)) % m. Ce qui met en évidence le problème: vous ne pouvez pas éviter la récursivité dans l'implémentation de factcar msera différent pour chaque itération de la boucle externe.
hvd
4

78 77 caractères

(Je viens d'appliquer quelques astuces apprises dans d'autres langues.)

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 caractères en mode 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);}
homme au travail
la source
2

58 caractères (ou 61 pour un programme complet)

Une autre réutilisation de ma réponse à une question similaire .
EDIT : morceau de code autonome, aucune fonction à appeler.

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

Programme complet:

n=2;main(m){n<999&&main(m<2?printf("%d\n",n),n:n%m?m-1:n++);}
ugoren
la source
1

67 64 octets

Inspiré par la solution d'Alchymist:

int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}
Sahil Arora
la source