Danh sách n số nguyên tố đầu tiên hiệu quả nhất và trong mã ngắn nhất [đã đóng]


27

Quy tắc rất đơn giản:

  • Số nguyên tố n đầu tiên (không phải số nguyên tố dưới n ), nên được in thành đầu ra tiêu chuẩn được phân tách bằng dòng mới (số nguyên tố phải được tạo trong mã)
  • Các số nguyên tố không thể được tạo bởi hàm inbuilt hoặc thông qua thư viện , nghĩa là sử dụng hàm inbuilt hoặc hàm thư viện, chẳng hạn như Prime = get_nth_prime (n), is_a_prime (number), hoặc listlist = list_all_factors (number) sẽ không sáng tạo.
  • Ghi điểm - Giả sử, chúng tôi xác định Điểm = f ([số ký tự trong mã]), O ( f (n)) là độ phức tạp của thuật toán của bạn trong đó n là số lượng số nguyên tố tìm thấy. Vì vậy, ví dụ: nếu bạn có mã 300 char với độ phức tạp O (n ^ 2), điểm số là 300 ^ 2 = 90000 , đối với 300 ký tự có O (n * ln (n)), điểm sẽ trở thành 300 * 5.7 = 1711.13 ( giả sử tất cả các bản ghi là bản ghi tự nhiên để đơn giản)

  • Sử dụng bất kỳ ngôn ngữ lập trình hiện có, chiến thắng điểm thấp nhất

Chỉnh sửa: Vấn đề đã được thay đổi từ việc tìm '1000000 số nguyên tố đầu tiên' thành 'số nguyên tố đầu tiên' vì nhầm lẫn về 'n' trong O (f (n)) là gì, n là số lượng số nguyên tố bạn tìm thấy (tìm số nguyên tố là vấn đề ở đây và sự phức tạp của vấn đề phụ thuộc vào số lượng các số nguyên tố được tìm thấy)

Lưu ý: để làm rõ một số nhầm lẫn về độ phức tạp, nếu 'n' là số nguyên tố bạn tìm thấy và 'N' là số nguyên tố thứ n được tìm thấy, độ phức tạp của n là và N không tương đương, ví dụ O (f (n))! = O (f (N)) as, f (N)! = Constant * f (n) và N! = Constant * n, bởi vì chúng ta biết rằng hàm số thứ n không phải là tuyến tính, mặc dù chúng ta đã tìm thấy 'n' độ phức tạp của số nguyên tố phải dễ dàng biểu thị theo 'n'.

Như Kibbee đã chỉ ra, bạn có thể truy cập trang web này để xác minh các giải pháp của mình ( ở đây , là danh sách tài liệu google cũ)

Vui lòng bao gồm những điều này trong giải pháp của bạn -

  • chương trình của bạn có phức tạp gì (bao gồm phân tích cơ bản nếu không tầm thường)

  • độ dài ký tự của mã

  • điểm tính toán cuối cùng

Đây là Câu hỏi CodeGolf đầu tiên của tôi vì vậy, nếu có sai sót hoặc kẽ hở trong các quy tắc trên, vui lòng chỉ ra chúng.


5
Đây là rất giống với codegolf.stackexchange.com/questions/5977/... .
Gareth

2
Câu trả lời của tôi cho một đó là 1[\p:i.78498câu trả lời của tôi cho đây sẽ là 1[\p:i.1000000. Ngay cả khi giả sử rằng thuật toán nguyên tố nội bộ của J là O (n ^ 2), điểm của tôi sẽ vẫn chỉ là 196.
Gareth

2
Không ai dường như quản lý để tính toán độ phức tạp của họ đúng cách. Có sự nhầm lẫn về việc nsố lượng số nguyên tố hay số nguyên tố tối đa và mọi người đều bỏ qua thực tế rằng việc thêm các số trong phạm vi 0..nO(logn), và phép nhân và phép chia thậm chí còn đắt hơn. Tôi đề nghị bạn nên đưa ra một số thuật toán ví dụ cùng với độ phức tạp đúng của họ.
ugoren

3
Thử nghiệm nguyên thủy được biết đến nhiều nhất hiện nay cho số k-bit là O-tilde(k^6). Điều này dẫn đến hàm ý rằng bất kỳ ai tuyên bố thời gian hoạt động tốt hơn O-tilde(n ln n (ln(n ln n))^6)đã hiểu sai một phần của vấn đề; và cho câu hỏi về mức O-tildeđộ phức tạp nên được xử lý trong việc tính điểm.
Peter Taylor

2
Không ai chỉ ra rằng O (n) tương đương với O (kn) (đối với hằng số k) về độ phức tạp, nhưng không phải về mặt điểm số. Ví dụ: giả sử độ phức tạp của tôi là O (n ^ 10). Điều đó tương đương với O (n ^ 10 * 1E-308), và tôi vẫn có thể chiến thắng thử thách với một chương trình khổng lồ với độ phức tạp khủng khiếp.
JDL

Câu trả lời:


10

Python (129 ký tự, O (n * log log n), điểm 203.948)

Tôi muốn nói rằng Sàng của Eratosthenes là con đường để đi. Rất đơn giản và tương đối nhanh.

N=15485864
a=[1]*N
x=xrange
for i in x(2,3936):
 if a[i]:
  for j in x(i*i,N,i):a[j]=0
print [i for i in x(len(a))if a[i]==1][2:]

Mã cải tiến từ trước.

Python ( 191 156 152 ký tự, O (n * log log n) (?), Điểm số 252.620 (?))

Tôi hoàn toàn không thể tính toán độ phức tạp, đây là xấp xỉ tốt nhất tôi có thể đưa ra.

from math import log as l
n=input()
N=n*int(l(n)+l(l(n)))
a=range(2,N)
for i in range(int(n**.5)+1):
 a=filter(lambda x:x%a[i] or x==a[i],a)
print a[:n]

n*int(l(n)+l(l(n)))ranh giới trên cùng của nsố nguyên tố thứ.


1
Tính toán phức tạp (và do đó điểm) dựa trên giới hạn trên nnhưng không dựa trên số lượng các số nguyên tố. Vì vậy, tôi cho rằng điểm số phải cao hơn. Xem bình luận của tôi ở trên.
Howard

Thượng giới n? Cái gì vậy
beary605

Giới hạn trên ở đây là N=15485864. Đối với các tính toán phức tạp dựa trên n=1000000, bạn có thể nói N=n*log(n)(vì mật độ của các số nguyên tố).
ugoren

Nếu điểm của tôi cần được sửa, xin vui lòng sửa nó cho tôi, tôi vẫn không hiểu rõ về hệ thống tính điểm.
beary605

@ beary605 sẽ ổn chứ nếu tôi sửa đổi các vấn đề để tìm n số nguyên tố đầu tiên? điều đó sẽ giải quyết rất nhiều sự nhầm lẫn về độ phức tạp và n là gì trong O (f (n))
Optimus

7

Haskell, n ^ 1.1 tốc độ tăng trưởng theo kinh nghiệm, 89 ký tự, điểm 139 (?)

Các hoạt động sau đây tại dấu nhắc GHCi khi thư viện chung mà nó sử dụng đã được tải trước đó. In số nguyên tố thứ n , dựa trên 1:

let s=3:minus[5,7..](unionAll[[p*p,p*p+2*p..]|p<-s])in getLine>>=(print.((0:2:s)!!).read)

Đây là sàng không giới hạn của Eratosthenes, sử dụng thư viện sử dụng chung cho các danh sách theo thứ tự. Độ phức tạp thực nghiệm giữa 100.000 và 200.000 số nguyên tố O(n^1.1). Phù hợp với O(n*log(n)*log(log n)).

Về ước tính phức tạp

Tôi đã đo thời gian chạy cho các số nguyên tố 100k và 200k, sau đó tính toán logBase 2 (t2/t1), sản xuất n^1.09. Xác định g n = n*log n*log(log n), tính toán logBase 2 (g 200000 / g 100000)cho n^1.12.

Sau đó 89**1.1 = 139, mặc dù g(89) = 600. --- (?)

Có vẻ như để ghi điểm tốc độ tăng trưởng ước tính nên được sử dụng thay vì chính chức năng phức tạp. Ví dụ, g2 n = n*((log n)**2)*log(log n)là tốt hơn nhiều so với n**1.5, nhưng đối với 100 ký tự số điểm hai sản phẩm của 32391000, tương ứng. Điều này không thể đúng. Ước tính trên phạm vi 200k / 100k cho logBase 2 (g2 200000 / g2 100000) = 1.2và do đó điểm số 100**1.2 = 251.

Ngoài ra, tôi không cố gắng in ra tất cả các số nguyên tố, thay vào đó là số nguyên tố thứ n .

Không nhập khẩu, 240 ký tự. n ^ 1,15 tốc độ tăng trưởng theo kinh nghiệm, điểm 546.

main=getLine>>=(print.s.read)
s n=let s=3:g 5(a[[p*p,p*p+2*p..]|p<-s])in(0:2:s)!!n
a((x:s):t)=x:u s(a$p t)
p((x:s):r:t)=(x:u s r):p t
g k s@(x:t)|k<x=k:g(k+2)s|True=g(k+2)t
u a@(x:r)b@(y:t)=case(compare x y)of LT->x:u r b;EQ->x:u r t;GT->y:u a t

5

Haskell, 72 89 ký tự, O (n ^ 2), Điểm 7921

Điểm cao nhất trên mỗi số char thắng phải không? Được sửa đổi cho lần đầu tiên N. Ngoài ra tôi dường như không thể sử dụng máy tính, vì vậy điểm của tôi không tệ đến mức như tôi nghĩ. (sử dụng độ phức tạp để phân chia thử nghiệm cơ bản như được tìm thấy trong nguồn dưới đây).

Theo Will Ness , bên dưới không phải là một chương trình Haskell đầy đủ (nó thực sự dựa vào REPL). Sau đây là một chương trình hoàn chỉnh hơn với một cái rây giả (việc nhập khẩu thực sự tiết kiệm được một char, nhưng tôi không thích nhập khẩu trong môn đánh gôn).

main=getLine>>= \x->print.take(read x).(let s(x:y)=x:s(filter((>0).(`mod`x))y)in s)$[2..]

Phiên bản này chắc chắn là (n ^ 2). Thuật toán chỉ là một phiên bản golf của '`sàng' 'ngây thơ, như được thấy ở đây Old ghci 1 liner

getLine>>= \x->print.take(read x)$Data.List.nubBy(\x y->x`mod`y==0)[2..]

Bỏ lại câu trả lời cũ, gian lận vì thư viện mà nó liên kết đến khá đẹp.

print$take(10^6)Data.Numbers.Primes.primes

Xem ở đây để thực hiện và các liên kết cho sự phức tạp thời gian. Thật không may, các bánh xe có thời gian tra cứu log (n), làm chậm chúng ta bởi một yếu tố.


• số nguyên tố không thể được tạo bởi một functon sẵn có hoặc thông qua thư viện
beary605

@walpen Tôi xin lỗi tôi đã sửa đổi các quy tắc mà không cần thông báo, vui lòng thực hiện các thay đổi khi bạn thấy phù hợp
Optimus

Sự phức tạp sẽ không giống như O ((n ln n) ^ 1,5 ln (n ln n) ^ 0,585)? (Hoặc O ((n n ln) ^ 1,5 ln (n ln n)) nếu Haskell sử dụng bộ phận ngây thơ chứ không phải là, như tôi đã giả định, Karatsuba)
Peter Taylor

Không, bởi vì điều đó mang lại cho tôi một số điểm khủng khiếp: /. Nhưng tôi chắc chắn rằng bạn đúng. Nó trông giống như phân chia thử nghiệm, và đó là sự phức tạp về thời gian của phân chia thử nghiệm (có thể, theo khả năng đọc hiểu kém của tôi về một nguồn có thể sai) vì vậy tôi đã chọn nó. Bây giờ tôi sẽ gọi điểm của mình là NaN, điều đó có vẻ an toàn.
walpen

Tôi giả sử (Haskell của tôi không đáng kể, nhưng tôi biết làm thế nào là tự nhiên khi làm điều đó trong SML ...) rằng bạn chỉ thực hiện phân chia thử nghiệm theo các số nguyên tố nhỏ hơn, trong đó phân chia thử nghiệm trên P làm O ( P ^ 0,5 / ln P) phân chia. Nhưng nếu P có k bit, một phép chia mất thời gian O (k ^ 1.585) (Karatsuba) hoặc O (k ^ 2) (ngây thơ) và bạn cần chạy qua các số O (n lg n) có độ dài O (ln ( n lg n)) bit.
Peter Taylor

5

C #, 447 ký tự, byte 452, điểm?

using System;namespace PrimeNumbers{class C{static void GN(ulong n){ulong primes=0;for (ulong i=0;i<(n*3);i++){if(IP(i)==true){primes++;if(primes==n){Console.WriteLine(i);}}}}static bool IP(ulong n){if(n<=3){return n>1;}else if (n%2==0||n%3==0){return false;}for(ulong i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){return false;}}return true;}static void Main(string[] args){ulong n=Convert.ToUInt64(Console.ReadLine());for(ulong i=0;i<n;i++){GN(i);}}}}

scriptcs Biến thể, 381 ký tự, 385 byte, điểm?

using System;static void GetN(ulong n){ulong primes=0;for (ulong i=0;i<(n*500);i++){if(IsPrime(i)==true){primes++;if(primes==n){Console.WriteLine(i);}}}}public static bool IsPrime(ulong n){if(n<=3){return n>1;}else if (n%2==0||n%3==0){return false;}for(ulong i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){return false;}}return true;}ulong n=Convert.ToUInt64(Console.ReadLine());for(ulong i=0;i<n;i++){GetN(i);}

Nếu bạn cài đặt scriptcs thì bạn có thể chạy nó.

PS tôi đã viết điều này trong Vim :D


2
Bạn có thể lưu một số ký tự bằng cách xóa một số khoảng trắng không cần thiết. Ví dụ, không cần thiết phải đặt khoảng trắng xung quanh một =<ký. Ngoài ra, tôi không nghĩ có sự khác biệt về byte và ký tự cho mã này - đó là 548 ký tự và 548 byte.
Chương trìnhFOX

2
Ồ cảm ơn, đây là CodeGolf đầu tiên của tôi!
XiKuuKy

4

GolfScript (45 ký tự, số điểm được yêu cầu ~ 7708)

~[]2{..3${1$\%!}?={.@\+\}{;}if)1$,3$<}do;\;n*

Điều này không phân chia thử nghiệm đơn giản theo số nguyên tố. Nếu ở gần đỉnh của Ruby (tức là sử dụng 1.9.3.0), số học sử dụng phép nhân Toom-Cook 3, do đó, một phép thử là O (n ^ 1.465) và chi phí chung của các phép chia là O((n ln n)^1.5 ln (n ln n)^0.465) = O(n^1.5 (ln n)^1.965). Tuy nhiên, trong GolfScript, việc thêm một phần tử vào một mảng đòi hỏi phải sao chép mảng đó. Tôi đã tối ưu hóa điều này để sao chép danh sách các số nguyên tố chỉ khi nó tìm thấy một số nguyên tố mới, do đó chỉ có ntổng số lần. Mỗi thao tác sao chép là O(n)các mục có kích thước O(ln(n ln n)) = O(ln n), cho O(n^2 ln n).

Và điều này, các chàng trai và cô gái, là lý do tại sao GolfScript được sử dụng để chơi gôn hơn là để lập trình nghiêm túc.

O(ln (n ln n)) = O(ln n + ln ln n) = O(ln n). Tôi nên đã phát hiện ra điều này trước khi bình luận về các bài viết khác nhau ...


4

Điều này rất dễ dàng ngay cả trình soạn thảo văn bản của tôi có thể làm điều này!

Vim: 143 tổ hợp phím (115 hành động): O (n ^ 2 * log (n)): Điểm: 101485,21

Nộp hồ sơ:

qpqqdqA^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddmpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@p

Đầu vào: N phải ở dòng đầu tiên của tài liệu trống. Sau khi kết thúc, mỗi số nguyên tố từ 2 đến N sẽ là một dòng riêng biệt.

Chạy các lệnh:

Đầu tiên, lưu ý rằng bất kỳ lệnh nào có dấu mũ ở phía trước chúng có nghĩa là bạn cần giữ Ctrl và nhập chữ cái tiếp theo (ví dụ ^ V là Ctrl-vvà ^ R là Ctrl-r).

Điều này sẽ ghi đè lên bất cứ điều gì trong các thanh ghi @a, @b, @d và @p của bạn.

Bởi vì điều này sử dụng qcác lệnh, nó không thể được đặt trong một macro. Tuy nhiên, đây là một số mẹo để chạy nó.

  • qpqqdq chỉ cần xóa sổ đăng ký
  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddsẽ tạo một danh sách các số từ 2 đến N + 1. Đây là một khoảng nghỉ giữa hai phần chính, vì vậy một khi điều này được thực hiện, bạn không cần phải làm lại
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@pkhông cần phải gõ trong một lần. Cố gắng tránh backspace vì nó có thể làm hỏng cái gì đó.
    • Nếu bạn mắc lỗi, hãy gõ qdqqpqlại dòng này.

Đối với N lớn, điều này rất chậm. Mất khoảng 27 phút để chạy N = 5000; xem xét bản thân cảnh báo.

Thuật toán:

Điều này sử dụng một thuật toán đệ quy cơ bản để tìm các số nguyên tố. Đưa ra một danh sách tất cả các số nguyên tố từ 1 đến A, A + 1 là số nguyên tố nếu nó không chia hết cho bất kỳ số nào trong danh sách các số nguyên tố. Bắt đầu tại A = 2 và thêm số nguyên tố vào danh sách khi chúng được tìm thấy. Sau khi N thu hồi, danh sách sẽ chứa tất cả các số nguyên tố lên đến N.

Phức tạp

Thuật toán này có độ phức tạp là O (nN), trong đó N là số đầu vào và n là số lượng các số nguyên tố lên đến N. Mỗi phép đệ quy kiểm tra n số và N thu hồi được thực hiện, cho O (nN).

Tuy nhiên, N ~ n * log (n), đưa ra độ phức tạp cuối cùng là O (n 2 * log (n)) ( https://en.wikipedia.org/wiki/Prime_number_theorem#Approimumations_for_the_nth_prime_number )

Giải trình

Không dễ để phân biệt luồng chương trình từ các lệnh vim, vì vậy tôi viết lại nó trong Python theo cùng một luồng. Giống như mã Vim, mã python sẽ báo lỗi khi đến cuối. Python không thích quá nhiều đệ quy; nếu bạn thử mã này với N> 150 hoặc hơn, nó sẽ đạt đến độ sâu đệ quy tối đa

N = 20
primes = range(2, N+1)

# Python needs these defined.
mark_p = b = a = -1

# Check new number for factors. 
# This macro could be wrapped up in @d, but it saves space to leave it separate.
def p():
    global mark_d, mark_p, primes, a
    mark_d = 0
    print(primes)
    a = primes[mark_p]
    d()      

# Checks factor and determine what to do next
def d():
    global mark_d, mark_p, a, b, primes
    b = primes[mark_d]
    if(a == b): # Number is prime, check the next number
        mark_p += 1
        p()
    else:
        if(a%b == 0): # Number is not prime, delete it and check next number
            del(primes[mark_p])
            p()
        else: # Number might be prime, try next possible factor
            mark_d += 1
            d()

mark_p = 0 #Start at first number         
p()

Bây giờ, để phá vỡ các tổ hợp phím thực tế!

  • qpqqdqXóa các thanh ghi @d và @p. Điều này sẽ đảm bảo không có gì chạy khi thiết lập các macro đệ quy này.

  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddBiến đầu vào thành một danh sách các số từ 2 đến N + 1. Mục nhập N + 1 bị xóa do tác dụng phụ của việc thiết lập macro @d.

    • Cụ thể, viết một macro làm tăng một số, sau đó sao chép nó trên dòng tiếp theo, sau đó nó viết 1 và thực hiện macro N lần này.
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qghi macro @d, thực hiện hàm d () ở trên. Câu lệnh "Nếu" rất thú vị để thực hiện trong Vim. Bằng cách sử dụng toán tử tìm kiếm *, có thể chọn một đường dẫn nhất định để theo dõi. Phá vỡ lệnh xuống hơn nữa chúng ta nhận được

    • mpqdĐặt dấu p ở đây và bắt đầu ghi macro @d. Dấu p cần được đặt để có một điểm được biết là nhảy tới khi nó chạy
    • o^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc> Viết văn bản câu lệnh if / other
    • 0*w*wyiWdd@0 thực sự thực thi câu lệnh if.
    • Trước khi thực hiện lệnh này, dòng sẽ chứa @a @b 0 0 `pj@p @a 0 (@a%@b) `pdd@p 0 `dj@d
    • 0 di chuyển con trỏ đến đầu dòng
    • *w*w Di chuyển con trỏ đến mã để thực thi tiếp theo

      1. if @a == @b, nghĩa là `pj@p, nó chuyển sang số tiếp theo cho @a và chạy @p trên nó.
      2. if @a! = @b và @ a% @ b == 0, nghĩa là `pdd@pxóa số hiện tại @a, sau đó chạy @p trên số tiếp theo.
      3. if @a! = @b và @ a %% b! = 0, nghĩa là `dj@dkiểm tra số tiếp theo cho @b để xem đó có phải là yếu tố của @a không
    • yiWdd@0 đưa lệnh vào thanh ghi 0, xóa dòng và chạy lệnh

    • q kết thúc ghi macro @d
  • Khi đây là lần chạy đầu tiên, `pdd@plệnh được chạy, xóa dòng N + 1.

  • qpmp"aywgg@dq ghi macro @p, lưu số dưới con trỏ, sau đó chuyển đến mục đầu tiên và chạy @d trên đó.

  • gg@p thực sự thực thi @p để nó sẽ lặp lại trên toàn bộ tệp.


3

QBASIC, 98 Chars, Độ phức tạp N Sqrt (N), Điểm 970

I=1
A:I=I+2
FOR J=2 TO I^.5
    IF I MOD J=0 THEN GOTO A
NEXT
?I
K=K+1
IF K=1e6 THEN GOTO B
GOTO A
B:

Tôi đã sửa đổi báo cáo vấn đề một chút, bây giờ tìm thấy các số nguyên tố đầu tiên, tôi xin lỗi vì không có thông báo
Optimus

Tôi cho rằng chúng ta có thể giả sử đầu vào "trong nguồn" cho chương trình này; tức là, đầu vào là chữ số ngay sau IF K=(vì vậy độ dài chương trình sẽ không bao gồm chữ số). Khi nó đứng, chương trình in n số nguyên tố đầu tiên không bao gồm 2 số có thể được sửa bằng cách thêm ?2vào lúc bắt đầu và thay đổi K=...thành K=...-1. Chương trình này cũng có thể được golfed một chút bằng cách lấy không gian ra khỏi J=2 TO, J=0 THEN, K=...-1 THEN, và bằng cách loại bỏ thụt. Tôi tin rằng kết quả này trong một chương trình 96 ký tự.
res

3

Scala 263 ký tự

Cập nhật để phù hợp với các yêu cầu mới. 25% mã thỏa thuận với việc tìm giới hạn trên hợp lý để tính các số nguyên tố dưới đây.

object P extends App{
def c(M:Int)={
val p=collection.mutable.BitSet(M+1)
p(2)=true
(3 to M+1 by 2).map(p(_)=true)
for(i<-p){
var j=2*i;
while(j<M){
if(p(j))p(j)=false
j+=i}
}
p
}
val i=args(0).toInt
println(c(((math.log(i)*i*1.3)toInt)).take(i).mkString("\n"))
}

Tôi có một cái rây quá.

Dưới đây là một bài kiểm tra thực nghiệm về chi phí tính toán, không được phân tích:

object PrimesTo extends App{
    var cnt=0
    def c(M:Int)={
        val p=(false::false::true::List.range(3,M+1).map(_%2!=0)).toArray
        for (i <- List.range (3, M, 2)
            if (p (i))) {
                var j=2*i;
                while (j < M) {
                    cnt+=1
                    if (p (j)) 
                        p(j)=false
                    j+=i}
            }
        (1 to M).filter (x => p (x))
    }
    val i = args(0).toInt
    /*
        To get the number x with i primes below, it is nearly ln(x)*x. For small numbers 
        we need a correction factor 1.13, and to avoid a bigger factor for very small 
        numbers we add 666 as an upper bound.
    */
    val x = (math.log(i)*i*1.13).toInt+666
    println (c(x).take (i).mkString("\n"))
    System.err.println (x + "\tcount: " + cnt)
}
for n in {1..5} ; do i=$((10**$n)); scala -J-Xmx768M P $i ; done 

dẫn đến số lượng sau:

List (960, 1766, 15127, 217099, 2988966)

Tôi không chắc làm thế nào để tính điểm. Có đáng để viết thêm 5 ký tự không?

scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.13).toInt+666) 
res42: List[Int] = List(672, 756, 1638, 10545, 100045, 1000419, 10068909, 101346800, 1019549994)

scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.3)toInt) 
res43: List[Int] = List(7, 104, 1119, 11365, 114329, 1150158, 11582935, 116592898, 1172932855)

Đối với n lớn hơn, nó làm giảm các phép tính khoảng 16% trong phạm vi đó, nhưng afaik cho công thức tính điểm, chúng ta không xem xét các yếu tố không đổi?

những cân nhắc về Big-O mới:

Để tìm các số nguyên tố 1 000, 10 000, 100 000, v.v., tôi sử dụng một công thức về mật độ của các số nguyên tố x => (math.log (x) * x * 1.3 xác định vòng ngoài tôi đang chạy.

Vì vậy, đối với các giá trị i trong 1 đến 6 => NPrimes (10 ^ i) chạy 9399, 133768 ... lần vòng lặp bên ngoài.

Tôi đã tìm thấy hàm O này lặp đi lặp lại với sự giúp đỡ từ nhận xét của Peter Taylor, người đã đề xuất một giá trị cao hơn nhiều cho phép lũy thừa, thay vì 1,01, ông đề xuất 1,5:

def O(n:Int) = (math.pow((n * math.log (n)), 1.01)).toLong

O: (n: Int) Dài

val ns = List(10, 100, 1000, 10000, 100000, 1000*1000).map(x=>(math.log(x)*x*1.3)toInt).map(O) 

ns: Danh sách [Dài] = Danh sách (102, 4152, 91532, 1612894, 25192460, 364664351)

 That's the list of upper values, to find primes below (since my algorithm has to know this value before it has to estimate it), send through the O-function, to find similar quotients for moving from 100 to 1000 to 10000 primes and so on: 

(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
40.705882352941174
22.045279383429673
17.62109426211598
15.619414543051187
14.47513863274964
13.73425213148954

Đây là chỉ tiêu, nếu tôi sử dụng 1,01 là số mũ. Đây là những gì bộ đếm tìm thấy theo kinh nghiệm:

ns: Array[Int] = Array(1628, 2929, 23583, 321898, 4291625, 54289190, 660847317)

(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
1.799140049140049
8.051553431205189
13.649578085909342
13.332251210010625
12.65003116535112
12.172723833234572

Hai giá trị đầu tiên là các giá trị ngoại lệ, vì tôi đã thực hiện một hiệu chỉnh không đổi cho công thức ước tính của mình cho các giá trị nhỏ (tối đa 1000).

Với đề xuất của Peter Taylors là 1,5, nó sẽ giống như:

245.2396265560166
98.8566987153728
70.8831374743478
59.26104390040363
52.92941829568069
48.956394784317816

Bây giờ với giá trị của tôi, tôi nhận được:

O(263)
res85: Long = 1576

Nhưng tôi không chắc chắn, tôi có thể kết hợp chức năng O của mình với các giá trị quan sát gần đến mức nào.


Xin lỗi tôi đã thực hiện một số thay đổi đối với tuyên bố vấn đề để giảm bớt sự mơ hồ liên quan đến sự phức tạp, (tôi chắc chắn giải pháp của bạn sẽ không thay đổi nhiều)
Optimus

Đây là thử nghiệm hiệu quả phân chia theo số nguyên tố. Số lần qua vòng lặp bên trong là O(M^1.5 / ln M)và mỗi lần bạn thực hiện O(ln M)công việc (bổ sung), vì vậy, tổng thể là như vậy O(M^1.5) = O((n ln n)^1.5).
Peter Taylor

Với ^ 1,02 thay vì ^ 1,5, def O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLongtôi tiến gần hơn đến các giá trị, theo kinh nghiệm tìm thấy với bộ đếm của tôi. Tôi chèn những phát hiện của tôi trong bài viết của tôi.
người dùng không xác định

3

Ruby 66 ký tự, Điểm O (n ^ 2) - 4356

lazycó sẵn từ Ruby 2.0 và 1.0/0là một mẹo hay để có phạm vi vô hạn:

(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j==0}}.take(n).to_a

1
Bạn có thể tắt một char bằng cách đổi nó thành(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
Qqwy

Hoặc thậm chí: (Điều này làm cho giải pháp kém hiệu quả hơn, nhưng nó không thay đổi giới hạn O (n²) phía trên) (2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a. Điều này làm mất đi hai nhân vật nữa.
Qqwy

Thay đổi tốt nó (2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)sẽ dẫn đến 61 ký tự.
Richie

2

Ruby, 84 ký tự, 84 byte, điểm số?

Điều này có lẽ là một chút quá mới mẻ cho những phần này, nhưng tôi đã có một thời gian vui vẻ để làm điều đó. Nó chỉ đơn giản là các vòng lặp cho đến khi f(số nguyên tố tìm thấy) bằng n, số lượng số nguyên tố mong muốn được tìm thấy.

Điều thú vị là với mỗi vòng lặp, nó tạo ra một mảng từ 2 đến một ít hơn số lượng được kiểm tra. Sau đó, nó ánh xạ từng phần tử trong mảng thành mô-đun của số ban đầu và phần tử, và kiểm tra xem liệu có bất kỳ kết quả nào bằng không.

Ngoài ra, tôi không có ý tưởng làm thế nào để ghi bàn.

Cập nhật

Mã được nén và bao gồm một giá trị (hoàn toàn tùy ý) cho n

n,f,i=5**5,0,2
until f==n;f+=1;p i if !(2...i).to_a.map{|j|i%j}.include?(0);i+=1;end

Nguyên

f, i = 0, 2
until f == n
  (f += 1; p i) if !(2...i).to_a.map{|j| i % j}.include?(0)
  i += 1
end

Các i += 1bit và untilvòng lặp là loại nhảy ra khỏi tôi như là các lĩnh vực để cải thiện, nhưng trên đường đua này tôi bị mắc kẹt. Dù sao, đó là niềm vui để nghĩ về.


2

Scala, 124 ký tự

object Q extends App{Stream.from(2).filter(p=>(2 to p)takeWhile(i=>i*i<=p)forall{p%_!= 0})take(args(0)toInt)foreach println}

Phân chia thử nghiệm đơn giản lên đến căn bậc hai. Do đó độ phức tạp phải là O (n ^ (1,5 + epsilon))

124 ^ 1,5 <1381, vậy đó có phải là điểm số của tôi không?


1

Perl - 94 ký tự, O (n log (n)) - Điểm: 427

perl -wle '$n=1;$t=1;while($n<$ARGV[0]){$t++;if((1x$t)!~/^1?$|^(11+?)\1+$/){print $t;$n++;}}'

Python - 113 ký tự

import re
z = int(input())
n=1
t=1
while n<z:
    t+=1
    if not re.match(r'^1?$|^(11+?)\1+$',"1"*t):
        print t
        n+=1

1

AWK, 96 86 byte

Phụ đề: Nhìn mẹ! Chỉ thêm và một số sổ sách kế toán!

Tập tin fsoe3.awk:

{for(n=2;l<$1;){if(n in L)p=L[n]
else{print p=n;l++}
for(N=p+n++;N in L;)N+=p
L[N]=p}}

Chạy:

$ awk -f fsoe3.awk <<< 5
2
3
5
7
11
$ awk -f fsoe3.awk <<< 1000 | wc -l
1000

BASH, 133 byte

Tập tin x.bash:

a=2
while((l<$1));do if((b[a]))
then((c=b[a]));else((c=a,l++));echo $a;fi;((d=a+c))
while((b[d]));do((d+=c));done
((b[d]=c,a++));done

Chạy:

$ bash x.bash 5
2
3
5
7
11
$ bash x.bash 1000 | wc -l
1000

Các số nguyên tố được tính bằng cách để các số nguyên tố đã tìm thấy nhảy vào "băng số nguyên dương". Về cơ bản nó là một Sàng Of Eratosthenes nối tiếp.

from time import time as t

L = {}
n = 2
l = 0

t0=t()

while l<1000000:

        if n in L:
                P = L[n]
        else:
                P = n
                l += 1
                print t()-t0

        m = n+P
        while m in L:
                m += P
        L[m] = P

        n += 1

... là cùng một thuật toán trong Python và in ra thời gian khi số lnguyên tố thứ được tìm thấy thay vì chính số nguyên tố đó.

Đầu ra âm mưu với gnuplotsản lượng như sau:

nhập mô tả hình ảnh ở đây

Các bước nhảy có thể có liên quan đến sự chậm trễ của tập tin do ghi dữ liệu vào bộ đệm vào đĩa ...

Sử dụng số lượng lớn các số nguyên tố cần tìm, sẽ mang lại độ trễ phụ thuộc hệ thống bổ sung vào trò chơi, ví dụ: mảng đại diện cho "băng số nguyên dương" phát triển liên tục và sớm hay muộn sẽ khiến mọi máy tính khóc vì RAM nhiều hơn (hoặc hoán đổi sau này).

... Vì vậy, việc có được ý tưởng về sự phức tạp bằng cách xem dữ liệu thử nghiệm không thực sự giúp ích nhiều ... :-(


Bây giờ đếm các bổ sung cần thiết để tìm các nsố nguyên tố:

cells = {}
current = 2
found = 0

additons = 0

while found < 10000000:

        if current in cells:
                candidate = cells[current]
                del cells[current] # the seen part is irrelevant
        else:
                candidate = current
                found += 1 ; additons += 1
                print additons

        destination = current + candidate ; additons += 1
        while destination in cells:
                destination += candidate ; additons += 1
        cells[destination] = candidate

        current += 1 ; additons += 1

nhập mô tả hình ảnh ở đây


Làm thế nào bạn tạo ra những biểu đồ?
con mèo

1
Gnuplotvới set term xtermvà sau đó ảnh chụp màn hình của xtermcửa sổ đồ họa (có thể là một tính năng gần bị lãng quên). ;-)

0

Scala 121 (99 không có bản tóm tắt lớp chính)

object Q extends App{Stream.from(2).filter{a=>Range(2,a).filter(a%_==0).isEmpty}.take(readLine().toInt).foreach(println)}

0

Trăn 3, 117 106 byte

Giải pháp này hơi tầm thường, vì nó xuất ra 0 trong đó một số không phải là số nguyên tố, nhưng dù sao tôi cũng sẽ đăng nó:

r=range
for i in[2]+[i*(not 0 in[i%j for j in r(3,int(i**0.5)+1,2)])for i in r(3,int(input()),2)]:print(i)

Ngoài ra, tôi không chắc làm thế nào để tìm ra sự phức tạp của một thuật toán. Xin đừng downvote vì điều này. Thay vào đó, hãy tử tế và nhận xét làm thế nào tôi có thể làm việc đó. Ngoài ra, cho tôi biết làm thế nào tôi có thể rút ngắn điều này.


Tôi nghĩ bạn có thể đặt print(i)cùng một dòng với vòng lặp for và xóa khoảng trắng tạiin [2] , 0 if, 0 in [i%j+1,2)] else.
acrolith

@daHugLenny Wow, cảm ơn rất nhiều! Tôi sẽ chỉnh sửa bài viết của mình trong giây lát. :-D
0WJYxW9FMN

@daHugLenny Bạn có biết cách tính hiệu quả bằng bất kỳ cơ hội nào không?
0WJYxW9FMN

Không xin lỗi. (Nhận xét phải dài ít nhất 15 ký tự)
acrolith

Dù sao cũng cảm ơn bạn. Bạn đã làm cho chương trình của tôi ngắn nhất ở đây!
0WJYxW9FMN


0

Perl 6, 152 byte, O (n log n log (n log n) log (log (n log n))) (?), 9594,79 điểm

Theo trang này , độ phức tạp của việc tìm tất cả các số nguyên tố lên đến n là O (n log n log log n); độ phức tạp ở trên sử dụng thực tế là số nguyên tố thứ n tỷ lệ với n log n.

my \N=+slurp;my \P=N*(N.log+N.log.log);my @a=1 xx P;for 2..P.sqrt ->$i {if @a[$i] {@a[$_*$i]=0 for $i..P/$i}};say $_[1] for (@a Z ^P).grep(*[0])[2..N+1]

không đủ điều kiện, hãy làm điều đó trong Wentel để đủ điều kiện
noɥʇʎԀʎzɐɹƆ

Xin lỗi, nhưng ý bạn là gì?
bb94

cho tiền thưởng (fiiiiiiiiilerrrrr)
noɥʇʎԀʎzɐɹƆ

0

Groovy (50 byte) - O (n * sqrt (n)) - Điểm 353.553390593

{[1,2]+(1..it).findAll{x->(2..x**0.5).every{x%it}}​}​

Lấy n và xuất ra tất cả các số từ 1 đến n là số nguyên tố.

Thuật toán tôi chọn chỉ xuất ra số nguyên tố n> 2, vì vậy cần thêm 1,2 ở đầu là bắt buộc.

Phá vỡ

x%it - Ngẫu nhiên sự thật nếu nó không chia hết, giả dối nếu có.

(2..x**0.5).every{...}- Đối với tất cả các giá trị giữa 2 và sqrt (x), đảm bảo rằng chúng không chia hết, để điều này trả về giá trị true, phải trả về true cho mọi .

(1..it).findAll{x->...} - Đối với tất cả các giá trị từ 1 đến n, hãy tìm tất cả các giá trị phù hợp với tiêu chí không chia hết cho 2 và sqrt (n).

{[1,2]+...}​ - Thêm 1 và 2, vì chúng luôn là số nguyên tố và không bao giờ được thuật toán bao phủ.


0

Vợt 155 byte

(let p((o'(2))(c 3))(cond[(>=(length o)n)(reverse o)][(ormap(λ(x)(= 0(modulo c x)))
(filter(λ(x)(<= x(sqrt c)))o))(p o(add1 c))][(p(cons c o)(add1 c))]))

Nó giữ một danh sách các số nguyên tố được tìm thấy và kiểm tra tính chia hết của mỗi số tiếp theo theo các số nguyên tố đã được tìm thấy. Hơn nữa, nó chỉ kiểm tra tối đa căn bậc hai của số đang được kiểm tra vì điều đó là đủ.

Ung dung:

(define(nprimes n)
  (let loop ((outl '(2))                   ; outlist having primes being created
             (current 3))                  ; current number being tested
  (cond
    [(>= (length outl) n) (reverse outl)]  ; if n primes found, print outlist.
    [(ormap (λ(x) (= 0 (modulo current x))) ; test if divisible by any previously found prime
            (filter                         ; filter outlist till sqrt of current number
             (λ(x) (<= x (sqrt current)))
             outl))
     (loop outl (add1 current)) ]           ; goto next number without adding to prime list
    [else (loop (cons current outl) (add1 current))] ; add to prime list and go to next number
    )))

Kiểm tra:

(nprimes 35)

Đầu ra:

'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149)

0

awk 45 (độ phức tạp N ^ 2)

khác awk, cho số nguyên tố lên tới 100 sử dụng như thế này

awk '{for(i=2;i<=sqrt(NR);i++) if(!(NR%i)) next} NR>1' <(seq 100)

mã golf được tính một phần là

{for(i=2;i<=sqrt(NR);i++)if(!(NR%i))next}NR>1

có thể được đặt trong một tập lệnh và chạy như awk -f prime.awk <(seq 100)


0

Javascript, 61 ký tự

f=(n,p=2,i=2)=>p%i?f(n,p,++i):i==p&&n--&alert(p)||n&&f(n,++p)

Tệ hơn một chút so với O (n ^ 2), sẽ hết dung lượng ngăn xếp cho n lớn.

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.