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);}
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);}
Réponses:
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
d=p++%999
. Sinon, cela semble être un travail de golf assez hermétique!
(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 p
de 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 n
est premier si et seulement si
fact(n-1)%n == n-1
où fact
est la fonction factorielle. Puisque vous testez tout le possible n
de 1
à 1000
, il est facile d'éviter d'implémenter le factoriel en gardant une trace du produit en cours d'exécution P
et en le mettant à jour P*=n
aprè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 n
satisfait
pow(a,n-1)%n == 1
Malheureusement, certains composites n
réussissent également ce test pour certains a
. Celles-ci sont appelées pseudoprimes Fermat . Mais, a=2
et a=3
n'é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.
int
s sont 32 bits. Il en va de même pour Fermat.
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
. ( m
est le module)
(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 fact
car m
sera différent pour chaque itération de la boucle externe.
(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);}
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);}
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++);}
Inspiré par la solution d'Alchymist:
int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}