Чи можна зробити цей код С меншим? Він друкує всі праймери від 0 до 1000.
C, 89 символів
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);}
Чи можна зробити цей код С меншим? Він друкує всі праймери від 0 до 1000.
C, 89 символів
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);}
Відповіді:
59 57 байт
На основі рішення @feersum, але перевірку первинності можна додатково програти в гольф
for(int p=1,d;d=p++%999;d||printf("%d\n",p))for(;p%d--;);
Відредаговано на основі коментарів Runer112
d=p++%999
. Інакше це виглядає досить герметичною роботою з гольфу!
(Я написав це, не розуміючи обмеження розміру на цілі числа в C, тому, ймовірно, це не корисно для скорочення коду.)
По-перше, слово про алгоритм. Перш ніж розіграти свій код, слід подумати про найкращу загальну стратегію для отримання результату.
Ви перевірка простоти, виконавши пробне розподіл - тестування кожен потенційний дільника p
з i
. Це дорого коштує в символах, оскільки для цього потрібно дві петлі. Отже, тестування первинності без циклу, ймовірно, врятує символів.
Часто коротший підхід полягає у використанні теореми Вілсона : число n
є простим, якщо і лише тоді
fact(n-1)%n == n-1
де fact
функціональна функція. Оскільки ви протестуєте все можливе n
від 1
до 1000
, легко уникнути впровадження факториуму, відстежуючи запущений продукт P
та оновлюючи його P*=n
після кожного циклу. Ось реалізація цієї стратегії Python для друку простих розмірів до мільйона.
Крім того, той факт, що у вашій програмі має бути до 1000, відкриває ще одну стратегію: тест перманентності Ферма . Для деяких a
кожен прем'єр n
задовольняє
pow(a,n-1)%n == 1
На жаль, деякі композити n
також для деяких проходять цей тест a
. Вони називаються псевдокринами Ферма . Але, a=2
і a=3
не провалюйтесь разом n=1105
, поки їх вистачить для вашої мети перевірки простих ліній до 1000. (Якщо 1000 замість цього 100, ви можете використовувати лише це a=2
.) Отже, ми перевіряємо примітивність за допомогою (невиявленого коду)
pow(2,n-1)%n == 1 and pow(3,n-1)%n == 1
Це також не вдається розпізнати прості 2 і 3, тому їх потрібно було б застосувати до спеціальних обставин.
Чи ці підходи коротші? Я не знаю, тому що я не кодую в C. Але це ідеї, які слід спробувати, перш ніж влаштуватися на шматок коду, щоб почати виписувати символи.
int
s є 32-розрядною. Те саме стосується і Ферма.
fact(int n, int m) { return (n==0) ? 1 : (n*f(n-1)) % m; }
результат не переллє 32-бітове ціле число для навіть досить великих значень n
. ( m
є модуль)
(n*fact(n-1,m)) % m
. Що підкреслює проблему: ви не можете уникнути рекурсії при здійсненні, fact
оскільки m
вона буде різною для кожної ітерації зовнішньої петлі.
(Просто застосуйте деякі хитрощі, вивчені іншими мовами.)
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);}
Ще одне повторне використання моєї відповіді на подібне запитання .
EDIT : автономна частина коду, без функції дзвінка.
for(int m,n=2;n<999;m>1?m=n%m--?m:n++:printf("%d\n",m=n));
Повна програма:
n=2;main(m){n<999&&main(m<2?printf("%d\n",n),n:n%m?m-1:n++);}
Натхненний рішенням Альхіміста:
int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}