Bu C kodunu küçültmek mümkün mü? 0 ile 1000 arasındaki tüm astarları yazdırır.
C, 89 karakter
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);}
Bu C kodunu küçültmek mümkün mü? 0 ile 1000 arasındaki tüm astarları yazdırır.
C, 89 karakter
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);}
Yanıtlar:
59 57 bayt
@Feersum çözümüne dayanmaktadır, ancak öncelik kontrolü daha fazla golf edilebilir
for(int p=1,d;d=p++%999;d||printf("%d\n",p))for(;p%d--;);
Runer112 adlı kullanıcının yorumlarına göre düzenlendi
d=p++%999
. Aksi takdirde, bu oldukça hava geçirmez golf işi görünüyor!
(Bunu, C'deki tamsayıların boyut sınırlamalarını fark etmediğini yazdım, bu yüzden kodu kısaltmak için muhtemelen kullanışlı değil.)
İlk olarak, algoritma hakkında bir kelime. Kodunuzu golf oynamadan önce, sonucu elde etmek için en iyi genel stratejiyi düşünmelisiniz.
Deneme bölümü yaparak asallık kontrol ediyoruz - Her potansiyel böleni test p
arasında i
. İki döngü gerektirdiğinden, bu karakterlerde maliyetlidir. Yani, bir döngü olmadan ilkeliğin test edilmesi karakterleri kurtarır.
Genellikle daha kısa bir yaklaşım Wilson Teoremini kullanmaktır : sayı n
sadece ve sadece
fact(n-1)%n == n-1
fact
faktöriyel fonksiyon nerede . Eğer mümkün olan tüm test aşamasında olduğu n
gelen 1
etmek 1000
, bu çalışan ürünün izleyerek faktöryel uygulama önlemek kolaydır P
ve bunu güncellenmesi P*=n
her döngü sonra. Bir milyona kadar prim basmak için bu stratejinin bir Python uygulaması .
Alternatif olarak, programınızın sadece 1000'e kadar olması gerektiği başka bir strateji daha açar: Fermat öncelik testi . Bazıları için a
her asal n
tatmin olur
pow(a,n-1)%n == 1
Ne yazık ki, bazı kompozitler n
bu testi bazıları için de geçmektedir a
. Bunlara Fermat psödoprimleri denir . Ancak, a=2
ve bugüne kadar a=3
birlikte başarısız olmayın n=1105
, bu yüzden 1000'e kadar primleri kontrol etme amacınız için yeterlidirler. (1000 yerine 100 olsaydı, sadece kullanabilirsiniz a=2
.) Yani, (kodsuz kod)
pow(2,n-1)%n == 1 and pow(3,n-1)%n == 1
Bu ayrıca primer 2 ve 3'ü tanıyamaz, bu nedenle bunların özel kasalı olması gerekir.
Bu yaklaşımlar daha mı kısa? Bilmiyorum çünkü C'de kod yazmıyorum. Ama, karakterleri eklemeye başlamak için bir kod parçasına yerleşmeden önce denemeniz gereken fikirler.
int
s 32 bittir. Aynı şey Fermat için de geçerli.
fact(int n, int m) { return (n==0) ? 1 : (n*f(n-1)) % m; }
, sonuç oldukça büyük değerleri için 32 bitlik bir tamsayı taşmaz n
. ( m
modül)
(n*fact(n-1,m)) % m
. Hangi sorunu vurgular: fact
çünkü m
dış döngü her yineleme için farklı olacaktır , çünkü uygulama özyinelemesini önleyemezsiniz .
Benzer bir soruya verdiğim cevabın yeniden kullanılması .
EDIT : bağımsız kod parçası, aramak için bir işlev yok.
for(int m,n=2;n<999;m>1?m=n%m--?m:n++:printf("%d\n",m=n));
Komple program:
n=2;main(m){n<999&&main(m<2?printf("%d\n",n),n:n%m?m-1:n++);}
Simyacı'nın çözümünden ilham alan:
int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}