Có thể làm cho mã C này nhỏ hơn? Nó in ra tất cả các số nguyên tố từ 0 đến 1000.
C, 89 ký tự
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);}
Có thể làm cho mã C này nhỏ hơn? Nó in ra tất cả các số nguyên tố từ 0 đến 1000.
C, 89 ký tự
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);}
Câu trả lời:
59 57 byte
Dựa trên giải pháp @feersum nhưng kiểm tra tính nguyên thủy có thể được đánh gôn thêm
for(int p=1,d;d=p++%999;d||printf("%d\n",p))for(;p%d--;);
Được chỉnh sửa dựa trên ý kiến của Runer112
d=p++%999
. Nếu không, điều này có vẻ khá công việc chơi golf!
(Tôi đã viết điều này không nhận ra các giới hạn kích thước trên các số nguyên trong C, vì vậy nó có thể không thực sự hữu ích cho việc rút ngắn mã.)
Đầu tiên, một từ về thuật toán. Trước khi đánh golf mã của bạn, bạn nên suy nghĩ về chiến lược tổng thể tốt nhất để có được kết quả.
Bạn đang kiểm tra tính nguyên thủy bằng cách thực hiện phân chia thử nghiệm - kiểm tra từng ước số tiềm năng p
của i
. Đó là tốn kém trong các nhân vật bởi vì nó cần hai vòng. Vì vậy, kiểm tra tính nguyên thủy mà không có vòng lặp có khả năng lưu các ký tự.
Một cách tiếp cận thường ngắn hơn là sử dụng Định lý Wilson : số n
là số nguyên tố khi và chỉ khi
fact(n-1)%n == n-1
nơi fact
là hàm giai thừa. Vì bạn đang thử nghiệm tất cả các khả năng n
từ đó 1
đến 1000
, nên dễ dàng tránh việc triển khai giai đoạn bằng cách theo dõi sản phẩm đang chạy P
và cập nhật nó P*=n
sau mỗi vòng lặp. Đây là một triển khai Python của chiến lược này để in số nguyên tố lên tới một triệu.
Ngoài ra, thực tế là chương trình của bạn chỉ phải đúng tới 1000 sẽ mở ra một chiến lược khác: bài kiểm tra tính nguyên thủy của Fermat . Đối với một số người a
, mọi thủ tướng đều n
thỏa mãn
pow(a,n-1)%n == 1
Thật không may, một số vật liệu tổng hợp n
cũng vượt qua bài kiểm tra này cho một số a
. Chúng được gọi là giả Fermat . Nhưng, a=2
và a=3
không thất bại cùng nhau cho đến khi n=1105
chúng đủ cho mục đích kiểm tra số nguyên tố của bạn cho đến 1000. (Nếu 1000 thay vì 100, bạn chỉ có thể sử dụng a=2
.) Vì vậy, chúng tôi kiểm tra tính nguyên thủy với (mã không mã hóa)
pow(2,n-1)%n == 1 and pow(3,n-1)%n == 1
Điều này cũng không nhận ra các số nguyên tố 2 và 3, vì vậy những số này sẽ cần phải được đặc biệt.
Là những cách tiếp cận ngắn hơn? Tôi không biết vì tôi không viết mã trong C. Nhưng, chúng là những ý tưởng bạn nên thử trước khi giải quyết một đoạn mã để bắt đầu loại bỏ các ký tự.
int
s là 32 bit. Fermat cũng vậy.
fact(int n, int m) { return (n==0) ? 1 : (n*f(n-1)) % m; }
thì kết quả sẽ không vượt quá số nguyên 32 bit cho các giá trị khá lớn của n
. ( m
là mô-đun)
(n*fact(n-1,m)) % m
. Điều này làm nổi bật vấn đề: bạn không thể tránh sự đệ quy trong quá trình thực hiện fact
bởi vì m
sẽ khác nhau cho mỗi lần lặp của vòng lặp bên ngoài.
Một cách sử dụng lại câu trả lời của tôi cho một câu hỏi tương tự .
EDIT : đoạn mã độc lập, không có chức năng gọi.
for(int m,n=2;n<999;m>1?m=n%m--?m:n++:printf("%d\n",m=n));
Hoàn thành chương trình:
n=2;main(m){n<999&&main(m<2?printf("%d\n",n),n:n%m?m-1:n++);}
Lấy cảm hứng từ giải pháp của Alchymist:
int i=1,p;for(;i++<1e3;p-i||printf("%d\n",i)){p=1;while(i%++p);}