Tất cả các số nguyên tố từ 0 đến 1000


9

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);}

6
Chỉ cần đánh dấu trước một số nhược điểm "Chúng tôi không muốn thử thách ngôn ngữ cụ thể", yêu cầu trợ giúp đánh golf một số mã là chủ đề và một câu chuyện khác với thử thách.
Martin Ender

4
Chúng ta có cần bảo tồn thuật toán, hay chỉ kết quả cuối cùng?
John Dvorak

Tôi bắt đầu tôi ở 2 để hoàn toàn chính xác, vì điều này in 0 và 1.
lịch sử

bạn đang cố gắng để làm cho mã thực thi nhanh hơn hoặc cố gắng sử dụng ít ký tự hơn trong mã nguồn?
dùng3629249

1
Vì bạn đang yêu cầu hỗ trợ với golf, sẽ rất hữu ích khi đưa số lượng ký tự của giải pháp hiện tại của bạn vào bài đăng của bạn (tôi thực hiện là 89).
Mark Reed

Câu trả lời:


7

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


2
Kiểm tra ràng buộc có thể được đánh gôn thêm một chút : d=p++%999. Nếu không, điều này có vẻ khá công việc chơi golf!
Run112

10

67 byte

Trong C không có sự thay thế thực sự cho phân chia thử nghiệm, nhưng nó chắc chắn có thể được đánh gôn một chút.

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

Yêu cầu khai báo ban đầu C99, tiết kiệm 1 byte.


6

(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 pcủ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ố nlà số nguyên tố khi và chỉ khi

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

nơi factlà hàm giai thừa. Vì bạn đang thử nghiệm tất cả các khả năng ntừ đó 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 Pvà cập nhật nó P*=nsau 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 nthỏ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 ncũ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=2a=3không thất bại cùng nhau cho đến khi n=1105chú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ự.


1
Định lý Wilson không hữu ích trong C vì ints là 32 bit. Fermat cũng vậy.
frageum

@feersum ơi, bắn đi. Đó cũng là một vấn đề đối với các nhân tố. Có một loại big-int?
xnor

@xnor Không tích hợp.
Martin Ender

1
nếu xác định 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. ( mlà mô-đun)
apnorton

@anorton Tôi nghĩ bạn có ý (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 factbởi vì msẽ khác nhau cho mỗi lần lặp của vòng lặp bên ngoài.
hvd

4

78 77 ký tự

(Chỉ cần áp dụng một số thủ thuật đã học bằng các ngôn ngữ khác.)

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 ký tự ở chế độ 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);}

2

58 ký tự (hoặc 61 cho một chương trình hoàn chỉnh)

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++);}

1

67 64 byte

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);}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.