Một máy phát nguyên tố xuất hiện tự nhiên


42

Có một số lượng lớn các hàm tạo số nguyên tố. Khá nhiều trong số chúng được chế tạo và dựa trên sàng của Eratosthenes, hàm Möbius hoặc định lý Wilson và thường không thể tính toán trong thực tế. Nhưng cũng có những máy phát điện, có cấu trúc rất dễ dàng và được tìm thấy một cách tình cờ.

Năm 2003, Stephen Wolfram đã khám phá một lớp phương trình tái phát lồng nhau trong một thí nghiệm máy tính trực tiếp tại Trường học hè NKS. Một nhóm người xung quanh Matthew Frank đã theo dõi các thí nghiệm bổ sung và phát hiện ra một tính chất thú vị của sự tái phát đơn giản

a(n) = a(n-1) + gcd(n,a(n-1))

với giá trị bắt đầu của a(1) = 7. Sự khác biệt a(n) - a(n-1) = gcd(n,a(n-1))dường như luôn luôn là 1 hoặc một số nguyên tố. Một số khác biệt đầu tiên là ( OEIS A132199 ):

1, 1, 1, 5, 3, 1, 1, 1, 1, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 3, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 3, 1, 5, 3, ...

Nếu chúng ta chỉ bỏ qua 1s, chúng ta sẽ nhận được chuỗi sau ( OEIS A137613 ):

5, 3, 11, 3, 23, 3, 47, 3, 5, 3, 101, 3, 7, 11, 3, 13, 233, 3, 467, 3, 5, 3, 
941, 3, 7, 1889, 3, 3779, 3, 7559, 3, 13, 15131, 3, 53, 3, 7, 30323, 3, ...

Eric S. Rowland đã chứng minh tính nguyên thủy của từng yếu tố trong danh sách này một vài năm sau đó. Như bạn có thể thấy, các số nguyên tố được trộn lẫn và một số trong số chúng xuất hiện nhiều lần. Nó cũng đã được chứng minh, trình tự bao gồm vô số các số nguyên tố khác nhau. Hơn nữa, nó được phỏng đoán, rằng tất cả các số nguyên tố lẻ xuất hiện.

Bởi vì máy phát nguyên tố này không được chế tạo mà chỉ được tìm thấy một cách tình cờ, nên máy phát nguyên tố được gọi là "tự nhiên". Nhưng lưu ý rằng trong thực tế, trình tạo này cũng không khả thi để tính toán. Hóa ra, một số nguyên tố p chỉ xuất hiện sau (p–3)/21 giây liên tiếp. Tuy nhiên, việc thực hiện trình tạo nguyên tố này sẽ là nhiệm vụ của bạn.

Thử thách:

Viết hàm hoặc chương trình in các nphần tử đầu tiên của chuỗi A137613(chuỗi không có 1s). Bạn có thể đọc số đầu vào n >= 0thông qua STDIN, đối số dòng lệnh, lời nhắc hoặc đối số hàm. Xuất các nphần tử đầu tiên ở bất kỳ định dạng nào có thể đọc được sang STDOUT hoặc trả về một mảng hoặc danh sách có các giá trị này.

Đây là mã golf. Do đó mã ngắn nhất sẽ thắng.

Bảng xếp hạng:

Dưới đây là Stack Snippet để tạo cả bảng xếp hạng thông thường và tổng quan về người chiến thắng theo ngôn ngữ. Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu câu trả lời của bạn bằng một tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

Trong đó N là kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
Trong khi trình tạo nguyên tố không được xây dựng, bạn đang triển khai hiệu quả một bộ phận dùng thử bằng cách sử dụng đệ quy.
orlp

Nếu a (1) = 7, tại sao chuỗi không bắt đầu bằng 7?
frageum

3
@feersum vì trình tự chúng tôi quan tâm làa(n)-a(n-1)
Maltysen

nthể bằng không?
Sp3000

1
@jrenk Không chắc lắm. Có thể tính nó là 2 byte (vì bạn đang xóa 2 ký tự //) và giải thích nó trong bài gửi của bạn. Nếu bất cứ ai không đồng ý với bạn, bạn luôn có thể chỉnh sửa bài đăng của mình.
Jakube

Câu trả lời:



7

Python 3.5.0b1 +, 95 93 byte

Liên kết với phiên bản Python 3.5.0b1 +

import math
def f(k,n=2,a=7,L=[]):x=math.gcd(n,a);return k and f(k-1%x,n+1,a+x,L+1%x*[x])or L

Một thực hiện trực tiếp của sự tái phát, có:

  • Người bạn tốt của chúng tôi 1%x, và
  • math.gcd, trái ngược với fractions.gcd.

Không gì 1%xlàm gì? Câu hỏi phụ: tôi tìm tài liệu về lịch sử sửa đổi của Python bao gồm betas ở đâu? Chỉnh sửa: Nevermind, tìm thấy nó ở dưới cùng của lịch sử sửa đổi .
mbomb007

@ mbomb007 Kể từ khi x >= 1, 1%xtrả về 0 nếu x == 1, 1 nếu không (được sử dụng để quyết định có thêm xvào danh sách hay không)
Sp3000

5

Julia, 110 byte

n->(a(n)=(n1&&(n==1?7:a(n-1)+gcd(n,a(n-1))));i=2;j=0;while j<n x=a(i)-a(i-1);x>1&&(j+=1;println(x));i+=1end)

Ung dung:

function a(n::Int)
    n  1 && (n == 1 ? 7 : a(n-1) + gcd(n, a(n-1)))
end

function f(n::Int)
    i = 2;
    j = 0;
    while j < n
        x = a(i) - a(i-1)
        if x > 1
            j += 1
            println(x)
        end
        i += 1
    end
end

Wow, một 8k hoàn hảo, tốt đẹp: D
Beta Decay

1
Sử dụng n<2thay vì n==1. Ngoài ra, nếu bạn nhìn về phía trước thay vì ngược lại, bạn có thể sử dụng i=1x=a(i)-a(i+=1), sau đó println(-x)-x>1để sửa lỗi cho sự tiêu cực, do đó tránh sự cần thiết phải tăng riêng i. Và là ba byte, trong khi >=là hai ... nhưng sau đó, bạn có thể sử dụng n<1||()chứ không phải n>=1&&()... tuy nhiên, ngay từ đầu, nó không cần thiết (bỏ điều kiện, n sẽ không bao giờ nhỏ hơn 1). Bạn cũng không cần dấu ngoặc ngoài cùng khi xác định (n). Với những thay đổi này, ít nhất bạn sẽ nhận được tới 97 byte.
Glen O

5

PHP, 101 96 99 98 77 72 byte

<?for(;2>$t=gmp_strval(gmp_gcd(~++$i,7+$e+=$t))or$argv[1]-=print"$t ";);


Cách sử dụng:
Gọi Script bằng một đối số: php -d error_reporting=0 script.php 30
Nếu bạn muốn kiểm tra nó, bạn cần bỏ ghi chú ;extension=php_gmp.dlltrong php.ini
-> extension=php_gmp.dll
Tôi có nên thêm phần mở rộng vào số byte của mình không? Có suy nghĩ gì không?


Nhật ký:
Đã lưu 3 byte nhờ Ismael Miguel.
Đã lưu 26 ​​byte nhờ primo.


1
Bạn có thể rút ngắn thẻ mở của bạn <?và xóa định nghĩa của $j.
Ismael Miguel

1
Vâng, nó có giá trị. Nhưng bạn có thể loại bỏ dòng mới đó. Việc này sẽ tiết kiệm 1-2 byte, tùy thuộc vào cách bạn đếm kích thước mã của mình.
Ismael Miguel

1
Cải tiến nhỏ: Sử dụng <trong $j<=$argv[1](in quá nhiều) (-1). Để lại $echưa được khởi tạo, sử dụng $e+7thay thế (-3). Sử dụng for(;;)thay vì while(), sử dụng các biểu thức trước và sau (-2). Thay thế echo$t.' ';$j++bằng $j+=print"$t ", thả dấu ngoặc (-3). Thay thế if($t>1)bằng 2>$t||(-2). Kết hợp việc chuyển nhượng tới $tvới điều kiện, chuyển ||cho or, thả các dấu ngoặc (-5). Di chuyển $argv[1]đến $jgia số, di chuyển toàn bộ biểu thức sang forđiều kiện (-2). Thay đổi >=$j+=printthành -=print(-3). Từng bước: codepad.org/s6LNSPSM
primo

1
@primo cảm ơn vì lời giải thích tốt đẹp! Không biết tôi có thể làm tất cả điều đó.
jrenk

1
Một vài điều nữa: Kết hợp $e+7với $e+=$t(-2). Để lại $ichưa được khởi tạo, sử dụng ~++$ithay thế (-3). codepad.org/fDIImajp
primo

4

Haskell, 51 byte

d=zipWith gcd[2..]$scanl(+)7d
f=($filter(>1)d).take

Lưu ý rằng đó flà một hàm sẽ trả về n phần tử đầu tiên .

Thay vì tính toán a(n)và sau đó tìm ra sự khác biệt, chúng tôi tính toán sự khác biệt d(n)và tổng hợp chúng lại với nhau để có được a(n). (Những người không quen thuộc với Haskell có thể phản đối rằng a(n)trước tiên chúng ta cần có được d(n), nhưng tất nhiên việc đánh giá lười biếng khiến chúng ta xoay quanh vấn đề này!)

Ung dung:

a = scanl (+) 7 d        -- yielding a(n) = 7 + d(1) + d(2) + ... + d(n-1)
d = zipWith gcd [2..] a  -- yielding d(n) = gcd(n+1, a(n))

f n = take n $ filter (> 1) d -- get rid of 1s and take the first n

4

Bình thường, 30 byte

Chơi golf rất tệ, có thể giảm đáng kể. Xác định hàm đệ quy ở phía trước, lọc .first-n và sau đó ánh xạ sự khác biệt.

L?tb+KytbibK7m-yhdyd.ft-yhZyZQ

Hãy thử nó ở đây trực tuyến .


Điều này cung cấp đầu ra sai chon = 0
Sp3000

2
@ Sp3000 đó là một lỗi trong Pyth. Tôi sẽ đưa ra yêu cầu kéo.
Maltysen

Đã tìm thấy và sửa lỗi - bản vá sẽ được triển khai khi github ngừng là DDoS'd.
isaacg

1
Đây là: meta.codegolf.stackexchange.com/questions/5318/ . Cá nhân tôi coi việc sửa lỗi trong các ngôn ngữ lập trình là một câu trả lời
Thomas Weller

2
@ThomasWeller Nó đạt được toàn bộ ngôn ngữ ...
isaacg

4

Julia, 69 67 byte

n->(i=1;a=7;while n>0 x=gcd(i+=1,a);a+=x;x>1&&(n-=1;println(x))end)

Đây là một giải pháp lặp đơn giản cho vấn đề. xlà sự khác biệt (là cái gcd), và sau đó tôi cập nhật abằng cách thêm x.


Tôi nghĩ rằng nó in A231900 .
alephalpha

@alephalpha - Tôi nghĩ tôi thấy lỗi. Dễ dàng sửa chữa. Thậm chí cạo hai byte trong quá trình.
Glen O

3

JavaScript (ES6), 91

Gcd đệ quy, chức năng chính lặp. Không quá nhanh.

Lưu ý thông thường: kiểm tra chạy đoạn mã trên bất kỳ trình duyệt tuân thủ EcmaScript 6 nào (đáng chú ý không phải Chrome không phải MSIE. Tôi đã thử nghiệm trên Firefox, Safari 9 có thể đi)

F=m=>{
  for(G=(a,b)=>b?G(b,a%b):a,o=[],p=7,n=1;m;d>1&&(o.push(d),--m))
    p+=d=G(++n,p);
  return o
}

O.innerHTML=F(+I.value)
<input id=I value=10><button onclick='O.innerHTML=F(+I.value)'>-></button>
<pre id=O></pre>


3

Haskell, 74 71 66 byte

f=($filter(>1)$tail>>=zipWith(-)$scanl(\x->(x+).gcd x)7[2..]).take

Đã sử dụng thủ thuật ở đây: https://codegolf.stackexchange.com/a/39730/43318 và thực hiện miễn phí điểm.

(Trước: 71 byte)

a=scanl(\x->(x+).gcd x)7[2..]
f m=take m$filter(>1)$zipWith(-)(tail a)a

Đầu tiên tạo chuỗi của a, và sau đó lấy sự khác biệt.

(Trước: 74 byte)

f m=take m$filter(>1)$map snd$scanl(\(x,d)->(\y->(x+y,y)).gcd x)(7,1)[2..]

Chức năng danh sách tiêu chuẩn, cộng với việc sử dụng thông minh chức năng lambda. Lưu ý đây là 1 byte ngắn hơn rõ ràng hơn

g m=take m$filter(>1)$map snd$scanl(\(x,d)n->(x+gcd x n,gcd x n))(7,1)[2..]

Nếu chúng ta không tính nhập khẩu, tôi có thể giảm xuống còn 66.

import Data.List
h m=take m$filter(>1)$snd$mapAccumL(\x->(\y->(x+y,y)).gcd x)7[2..]

3

PARI / GP, 60 byte

a(n)=a=7;i=1;while(n,if(1<d=gcd(i+=1,a),n-=1;print(d));a+=d)

Lấy ít nhiều thẳng từ định nghĩa a (n) - a (n-1) = gcd (n, a (n-1))

Đầu ra cho a(20):

5
3
11
3
23
3
47
3
5
3
101
3
7
11
3
13
233
3
467
3

2

C ++, 193 182 180 172 byte

Cảm ơn @Jakube - đã lưu 8 byte khi xuất.

int g(int a,int b){return a==b?a:a>b?g(b,a-b):g(a,b-a);}void f(int *r,int n){int m=1,i=0,a=7,b;while(i<n){b=g(a,++m);if(b>1){r[i]=b;++i;}a+=b;}}int main(){int r[6];f(r,6);}

Bạn có thể có thể lưu một vài byte bằng cách xác định hàm f, trả về một mảng với kết quả. Bằng cách này, bạn có thể loại bỏ bao gồm, scanf và in.
Jakube

2

Toán học, 59 byte

For[i=j=1;a=7,i<=#,,d=GCD[++j,a];If[d>1,Print@d;i++];a+=d]&
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.