is_gaussian_prime (z)?


23

Bài tập

Viết hàm chấp nhận hai số nguyên a,bbiểu thị số nguyên Gaussian z = a+ib(số phức). Chương trình này phải hoàn trả đúng hay sai tùy thuộc vào việc a+iblà một thủ Gaussian hay không .

Định nghĩa:

a + bi là một số nguyên tố Gaussian khi và chỉ khi nó đáp ứng một trong các điều kiện sau:

  • abcả hai đều khác nhau và a^2 + b^2là số nguyên tố
  • abằng không, |b|là số nguyên tố và|b| = 3 (mod 4)
  • bbằng không, |a|là số nguyên tố và|a| = 3 (mod 4)

Chi tiết

Bạn chỉ nên viết một chức năng. Nếu ngôn ngữ của bạn không có chức năng, bạn có thể giả sử rằng các số nguyên được lưu trữ trong hai biến và in kết quả hoặc ghi nó vào một tệp.

Bạn không thể sử dụng được xây dựng trong chức năng của ngôn ngữ của bạn như isprimehoặc prime_listhoặc nthprimehoặc factor. Số byte thấp nhất sẽ thắng. Chương trình phải hoạt động a,bở nơi a^2+b^2có số nguyên 32 bit (đã ký) và sẽ kết thúc sau không quá 30 giây.

Danh sách chính

Các dấu chấm đại diện cho số nguyên tố trên mặt phẳng Gaussian ( x= real, y= trục ảo):

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

Một số số nguyên tố lớn hơn:

(9940, 43833)
(4190, 42741)
(9557, 41412)
(1437, 44090)

2
Chúng ta có được phép sử dụng các hàm nhân tố không ( factortrong Bash mfmFtrong CJam, ...)

Ồ không, tôi đã quên các phương thức nhân tố tồn tại, không xin vui lòng không =) Và giới hạn 32 bit áp dụng cho ^ 2 + b ^ 2, sẽ không có ý nghĩa gì khác. Cảm ơn bạn cho đầu vào của bạn! Tôi cập nhật câu hỏi.
flawr

2
Tôi đã thêm một định nghĩa về số nguyên tố Gaussian vào bài viết. Nếu bạn không thích cách tôi đã thực hiện, hãy thoải mái cuộn lại, nhưng tôi chắc chắn sẽ khuyên bạn nên đưa vào định nghĩa ở đâu đó.
undergroundmonorail

Thật tuyệt, ban đầu tôi chỉ không muốn trực tiếp chỉ ra cách xác định tính nguyên thủy để mọi người có thể sáng tạo =)
flawr

1 1073741857 đối với tôi không phải là số nguyên tố Gaussian vì 1 ^ 2 + 1073741857 ^ 2 là một số chẵn ...
RosLuP

Câu trả lời:


4

Haskell - 77/ 108 107 Chars

cách sử dụng: trong cả hai giải pháp, gõ% b sẽ trả về việc a + bi có phải là số nguyên tố gaussian hay không.

thấp nhất tôi quản lý, nhưng không có sáng tạo hoặc hiệu suất (77 ký tự)

p n=all(\x->rem n x>0)[2..n-1]
a%0=rem a 4==3&&p(abs a)
0%a=a%0
a%b=p$a^2+b^2

giải pháp này chỉ cấp nguồn qua tất cả các số dưới n để kiểm tra xem nó có phải là số nguyên tố hay không.

phiên bản không có bản quyền:

isprime = all (\x -> rem n x != 0) [2..n-1] -- none of the numbers between 2 and n-1 divide n.
isGaussianPrime a 0 = rem a 4==3 && isprime (abs a)
isGaussianPrime 0 a = isGaussianPrime a 0   -- the definition is symmetric
isGaussianPrime a b = isprime (a^2 + b^2)

giải pháp tiếp theo có một tính năng bổ sung - ghi nhớ. một khi bạn kiểm tra xem một số nguyên n có phải là số nguyên tố hay không, bạn sẽ không cần tính toán lại "độ nguyên thủy" của tất cả các số nhỏ hơn hoặc bằng n, vì nó sẽ được lưu trong máy tính.

(107 ký tự. Các ý kiến ​​là rõ ràng)

s(p:x)=p:s[n|n<-x,rem n p>0] --the sieve function
l=s[2..]                     --infinite list of primes
p n=n==filter(>=n)l!!0       --check whether n is in the list of primes
a%0=rem a 4==3&&p(abs a)
0%a=a%0
a%b=p$a*a+b*b

phiên bản không có bản quyền:

primes = sieve [2..] where
    sieve (p:xs) = p:filter (\n -> rem n p /= 0) xs
isprime n = n == head (filter (>=n) primes) -- checks if the first prime >= n is equal to n. if it is, n is prime.
isGaussianPrime a 0 = rem a 4==3 && isprime (abs a)
isGaussianPrime 0 a = isGaussianPrime a 0   -- the definition is symmetric
isGaussianPrime a b = isprime (a^2 + b^2)

cái này sử dụng sàng của Eratosthenes để tính toán một danh sách vô hạn của tất cả các số nguyên tố (được gọi là l cho danh sách trong mã). (danh sách vô hạn là một thủ thuật nổi tiếng của haskell).

làm thế nào có thể có một danh sách vô hạn? khi bắt đầu chương trình, danh sách này không được đánh giá và thay vì lưu trữ các phần tử danh sách, máy tính sẽ lưu trữ cách tính toán chúng. nhưng khi chương trình truy cập vào danh sách, nó sẽ tự đánh giá một phần theo yêu cầu. vì vậy, nếu chương trình yêu cầu mục thứ tư trong danh sách, máy tính sẽ tính tất cả các số nguyên tố cho đến khi chưa được đánh giá, lưu trữ chúng và phần còn lại sẽ không được đánh giá, được lưu trữ như một cách để tính toán chúng một lần cần thiết

lưu ý rằng tất cả những điều này được đưa ra một cách tự do bởi bản chất lười biếng của ngôn ngữ Haskell, không có gì trong số đó là rõ ràng từ chính mã.

cả hai phiên bản của chương trình đều bị quá tải, vì vậy chúng có thể xử lý dữ liệu có kích thước tùy ý.


Theo tính toán của tôi, giải pháp đầu tiên của bạn thực sự là 77 ký tự: D
killmous

tôi đã tính các dòng mới, phải không?
tự hào

Tôi đếm 74 nhân vật thông thường và 3 dòng mới
killmous

bạn nói đúng, có vẻ như vì một số lý do notepad ++ thêm ký tự trước dòng mới. cảm ơn!
tự hào

đó là lý do tại sao tôi sử dụng cao siêu;) rất vui được giúp đỡ!
sát thủ

9

C, 149 118 ký tự

Phiên bản đã chỉnh sửa (118 ký tự):

int G(int a,int b){a=abs(a);b=abs(b);int n=a*b?a*a+b*b:a+b,
d=2;for(;n/d/d&&n%d;d++);return n/d/d|n<2?0:(a+b&3)>2|a*b;}

Đây là một chức năng duy nhất:

  • G ( a , b ) trả về giá trị khác không (true) nếu a + bi là số nguyên tố Gaussian hoặc zero (false) nếu không.

Nó gấp bài kiểm tra nguyên thủy số nguyên thành một biểu thức n/d/d|n<2ẩn trong phép tính giá trị trả về. Mã đánh gôn này cũng sử dụng a*bthay thế cho a&&b(nói cách khác a!=0 && b!=0) và các thủ thuật khác liên quan đến quyền ưu tiên của toán tử và phép chia số nguyên. Ví dụ n/d/dlà một cách ngắn hơn để nói n/d/d>=1, đó là một cách tràn an toàn nói n>=d*dhay d*d<=nhay trong bản chất d<=sqrt(n).


Phiên bản gốc (149 ký tự):

int Q(int n){int d=2;for(;n/d/d&&n%d;d++);return n/d/d||n<2;}
int G(int a,int b){a=abs(a);b=abs(b);return!((a|b%4<3|Q(b))*(b|a%4<3|Q(a))*Q(a*a+b*b));}

Chức năng:

  • Q ( n ) trả về 0 (sai) nếu n là số nguyên tố hoặc 1 (đúng) nếu n là không có thời gian. Đây là một hàm trợ giúp cho G ( a , b ).

  • G ( a , b ) trả về 1 (đúng) nếu a + bi là số nguyên tố Gaussian hoặc 0 (sai) nếu không.

Sản lượng mẫu (tăng 200%) cho | một |, | b | ≤ 128:

Mẫu128


2
+1 cho hình ảnh! Bạn cũng có thể làm một cái có cùng kích thước chỉ trong góc phần tư thứ nhất (vì tính đối xứng), nó thực sự trông rất tuyệt ở đây =)
flawr

Bạn có thể lưu một vài ký tự bằng cách thay thế d = 2; for (; n / d / d && n% d; d ++); với for (d = 2; n / d / d && n% d ++;);
Alchymist

@Alchymist - Điều đó thực sự lưu các ký tự, nhưng tạo ra kết quả không chính xác. Điều quan trọng là việc d++không xảy ra như là một phần của điều kiện, nếu không nó sẽ làm rối logic sau. Ngoài ra, di chuyển d=2bên trong forvòng lặp thực sự làm tăng số lượng ký tự thay vì giảm nó, bởi vì dvẫn cần phải được khai báo như inttrước forvòng lặp. Tui bỏ lỡ điều gì vậy?
Todd Lehman

Quá đúng. Những nguy hiểm khi nhìn vào điều này từ một môi trường mã hóa và không đủ chặt chẽ. Gia tăng phải ở đúng vị trí của nó và việc khởi tạo chỉ giúp giải pháp ban đầu của bạn. Có những khoản tiết kiệm rõ ràng nếu bạn khai báo n & d bên ngoài hàm, mà không chỉ định int và khởi tạo chúng trong vòng lặp for nhưng tôi giả sử bạn đang thực hiện chức năng khép kín, đó là một cách giải thích nghiêm ngặt các yêu cầu.
Alchymist

1
Vòng lặp thử nghiệm chính ở đây là một số golf tuyệt vời! Tuy nhiên, có thể đạt được nhiều khoản tiết kiệm hơn nữa bằng cách bỏ các chỉ định kiểu int cho kiểu trả về và đối số, sử dụng biến cho | a | + | b | và tối ưu hóa câu lệnh return: G(a,b){int s=abs(a)+abs(b),n=a*b?a*a+b*b:s,d=2;for(;n/d/d&&n%d;d++);return n>1>n/d/d&&s%4/3|a*b;}xuất hiện chỉ 97 ký tự.
frageum

4

APL (Dyalog Unicode) , 36 47 48 49 47 43 28 byte

Lấy một mảng gồm hai số nguyên a bvà trả về giá trị Boolean của câu lệnha+bi is a Gaussian integer .

Chỉnh sửa: +11 byte vì tôi đã hiểu sai định nghĩa của một nguyên tố Gaussian. +1 byte từ việc sửa câu trả lời một lần nữa. +1 byte từ bản sửa lỗi thứ ba. -2 byte do sử dụng tàu thay vì dfn. -4 byte nhờ ngn do sử dụng bộ bảo vệ condition: if_true ⋄ if_falsethay vì if_true⊣⍣condition⊢if_false. -15 byte nhờ ngn do tìm ra một cách hoàn toàn khác để viết điều kiện-if-other như một chuyến tàu đầy đủ.

{2=≢∪⍵∨⍳⍵}|+.×0∘∊⊃|{⍺⍵}3=4||

Hãy thử trực tuyến!

Giải trình

{2=≢∪⍵∨⍳⍵}|+.×0∘∊⊃|{⍺⍵}3=4||

                           |   abs(a), abs(b) or abs(list)
                       3=4|    Check if a and b are congruent to 3 (mod 4)
                  |{⍺⍵}        Combine with (abs(a), abs(b))
              0∘∊⊃             Pick out the original abs(list) if both are non-zero
                               Else pick out (if 3 mod 4)
          |+.×                 Dot product with abs(list) returns any of
                               - All zeroes if neither check passed
                               - The zero and the number that IS 3 mod 4
                               - a^2 + b^2
{2=≢∪⍵∨⍳⍵}                     Check if any of the above are prime, and return

3

Haskell - 121 ký tự (bao gồm dòng mới)

Đây là một giải pháp Haskell tương đối đơn giản, không sử dụng bất kỳ mô-đun bên ngoài nào và được chơi nhiều nhất có thể.

a%1=[]
a%n|n`mod`a<1=a:2%(n`div`a)|1>0=(a+1)%n
0#b=2%d==[d]&&d`mod`4==3where d=abs(b)
a#0=0#a
a#b=2%c==[c]where c=a^2+b^2

Gọi ghci ./gprimes.hsvà sau đó bạn có thể sử dụng nó trong vỏ tương tác. Lưu ý: số âm là rất khó và phải được đặt trong ngoặc đơn. I E

*Main>1#1
True
*Main>(-3)#0
True
*Main>2#2
False

3

Python - 121 120 ký tự

def p(x,s=2):
 while s*s<=abs(x):yield x%s;s+=1
f=lambda a,b:(all(p(a*a+b*b))if b else f(b,a))if a else(b%4>2)&all(p(b))

pkiểm tra xem có phải abs(x)là số nguyên tố hay không bằng cách lặp qua tất cả các số từ 2 đến abs(x)**.5(đó là sqrt(abs(x))). Nó làm như vậy bằng cách x % scho năng suất cho mỗi s. allsau đó kiểm tra xem tất cả các giá trị mang lại có khác không và dừng tạo giá trị một khi nó gặp ước số x. Trong f, f(b,a)thay thế trường hợp cho b==0, lấy cảm hứng từ câu trả lời Haskell của @killmous .


-1 char và sửa lỗi từ @PeterTaylor


Vui mừng tôi có thể giúp :)
killmous

Bạn có thể thay thế s<abs(x)**.5với s*s<abs(x)một tiết kiệm 2. Mặc dù thực sự bạn nên kiểm tra <=, vì vậy nó có thể là lỗi hiện nay.
Peter Taylor

@PeterTaylor Cảm ơn bạn đã chỉ ra lỗi ...
hlt

Gọi f(0,15)năng suất TypeError: unsupported operand type(s) for &: 'bool' and 'generator'với thông dịch viên của tôi. :(
Falko

f(0,15)cung cấp Falsecho tôi, cả trên 2.7.6 và 3.4.1 (trên OS X). Bạn ở phiên bản nào?
hlt

3

Python 2.7 , 341 301 253 byte, được tối ưu hóa cho tốc độ

lambda x,y:(x==0and g(y))or(y==0and g(x))or(x*y and p(x*x+y*y))
def p(n,r=[2]):a=lambda n:r+range(r[-1],int(n**.5)+1);r+=[i for i in a(n)if all(i%j for j in a(i))]if n>r[-1]**2else[];return all(n%i for i in r if i*i<n)
g=lambda x:abs(x)%4>2and p(abs(x))

Hãy thử trực tuyến!

#pRimes. need at least one for r[-1]
r=[2]
#list of primes and other to-check-for-primarity numbers 
#(between max(r) and sqrt(n))
a=lambda n:r+list(range(r[-1],int(n**.5)+1))
#is_prime, using a(n)
f=lambda n:all(n%i for i in a(n))
#is_prime, using r
def p(n):
    global r
    #if r is not enough, update r
    if n>r[-1]**2:
        r+=[i for i in a(n) if f(i)]
    return all(n%i for i in r if i*i<n)
#sub-function for testing (0,y) and (x,0)
g=lambda x:abs(x)%4==3 and p(abs(x))
#the testing function
h=lambda x,y:(x==0 and g(y)) or (y==0 and g(x)) or (x and y and p(x*x+y*y))

Cảm ơn: 40 +48 - toàn bộ việc chơi golf với Jo King


Các flambda cũng là uneccesary, cùng với các listcuộc gọi. 257 byte mà không có những cái đó, cộng với một số loại bỏ khoảng trắng. Điều này có lẽ không còn hiệu quả nữa
Jo King

(15,0) hiện đúng với phiên bản 257 byte và thời gian chạy tăng quá 5,5 giây, xin lỗi
Alexey Burdin

2

Perl - 110 107 105 ký tự

Tôi hy vọng tôi đã làm theo đúng định nghĩa được liên kết ...

sub f{($a,$b)=map abs,@_;$n=$a**(1+!!$b)+$b**(1+!!$a);(grep{$n%$_<1}2..$n)<2&&($a||$b%4>2)&&($b||$a%4>2)}

Ung dung:

sub f {
  ($a,$b) = map abs, @_;
  $n = $a**(1+!!$b) + $b**(1+!!$a);
  (grep {$n%$_<1} 2..$n)<2 && ($a || $b%4==3) && ($b || $a%4==3)
}

Giải thích, vì có người hỏi: Tôi đọc các đối số ( @_) và đặt giá trị tuyệt đối của họ vào $a, $bvì các chức năng không cần phải đăng nhập của họ. Mỗi tiêu chí yêu cầu kiểm tra tính nguyên thủy của một số, nhưng con số này phụ thuộc vào việc có $ahay $bkhông, mà tôi đã cố gắng thể hiện theo cách ngắn nhất và đưa vào $n. Cuối cùng tôi kiểm tra xem có phải $nlà số nguyên tố hay không bằng cách đếm có bao nhiêu số giữa 2 và chính nó chia nó mà không có phần dư (đó là grep...<2phần), và sau đó kiểm tra xem nếu một trong các số đó bằng 0 thì số kia bằng 3 modulo 4. Hàm số giá trị trả về theo mặc định là giá trị của dòng cuối cùng của nó và các điều kiện này trả về một số giá trị trung thực nếu tất cả các điều kiện được đáp ứng.


Tôi không thể làm cho nó hoạt động cho các tham số tiêu cực.
sát thủ

1
@killmous bạn nói đúng, chỉ cần sửa nó
Tal

bạn có thể giải thích thuật toán?
tự hào

1
Đẹp! Nhân tiện, tôi nghĩ bạn có thể cạo một vài ký tự bằng cách viết $a%4>2thay vì $a%4==3.
Todd Lehman

2

golflua 147 141

Số lượng trên bỏ qua các dòng mới mà tôi đã thêm để xem các chức năng khác nhau. Mặc dù khăng khăng không làm như vậy, tôi vũ phu giải quyết các số nguyên tố trong các vụ án.

\p(x)s=2@s*s<=M.a(x)?(x%s==0)~0$s=s+1$~1$
\g(a,b)?a*b!=0~p(a^2+b^2)??a==0~p(b)+M.a(b)%4>2??b==0~p(a)+M.a(a)%4>2!?~0$$
w(g(tn(I.r()),tn(I.r())))

Trả về 1 nếu đúng và 0 nếu không.

Một phiên bản Lua vô danh,

-- prime number checker
function p(x)
   s=2
   while s*s<=math.abs(x) do
      if(x%s==0) then return 0 end
      s=s+1
   end
   return 1
end

-- check gaussian primes
function g(a,b)
   if a*b~=0 then
      return p(a^2+b^2)
   elseif a==0 then
      return p(b) + math.abs(b)%4>2
   elseif b==0 then
      return p(a) + math.abs(a)%4>2
   else
      return 0
   end
end


a=tonumber(io.read())
b=tonumber(io.read())
print(g(a,b))

Bạn có thể tiết kiệm 6 ký tự bằng cách chỉ cần cắm tonumber(io.read())như một đối số gcuối cùng, và 2 hơn bằng cách loại bỏ các dòng mới
mniip

@mniip: các dòng mới không được tính, tôi chỉ thêm những dòng này cho rõ ràng (không cuộn sang một bên). Tôi sẽ cập nhật phần đọc trong g khi tôi đi làm một lát. Cảm ơn!
Kyle Kanos

Nó vẫn hoạt động trong một khoảng thời gian hợp lý cho số lượng lớn? Tôi chủ yếu nghĩ về bruteforcing theo cách kiểm tra tất cả các số nguyên gaussian atrong đó |a| <= |z|if a | z(if achia z).
flawr

@flawr: Tôi đã thử nghiệm nó với a = 2147483644, b = 896234511 và nhận 0 trong khoảng 0,002 s. Tôi cũng đã thử nghiệm nó với 2147483629 & 2147483587 (hai số nguyên tố rất lớn) và nhận được 0 trong 0,002 giây khác. Tôi đang cố gắng tìm một cặp số lớn sao cho ^ 2 + b ^ 2 là số nguyên tố & đảm bảo rằng tôi đã có giải pháp làm việc cho những số lớn như vậy.
Kyle Kanos

@flawr: Đã thử nghiệm với a = 4600 & b = 5603 (a ^ 2 + b ^ 2 = 2147393609 là số nguyên tố & <2 ^ 32-1) và phải mất 0,002 giây để quay lại 1. Yay!
Kyle Kanos

1

APL (NARS), 99 ký tự, 198 byte

r←p w;i;k
r←0⋄→0×⍳w<2⋄i←2⋄k←√w⋄→3
→0×⍳0=i∣w⋄i+←1
→2×⍳i≤k
r←1

f←{v←√k←+/2*⍨⍺⍵⋄0=⍺×⍵:(p v)∧3=4∣v⋄p k}

kiểm tra:

  0 f 13
0
  0 f 9
0
  2 f 3
1
  3 f 4
0
  0 f 7
1
  0 f 9
0
  4600 f 5603
1  

1

Runic bùa mê , 41 byte

>ii:0)?\S:0)?\:*S:*+'PA@
3%4A|'S/;$=?4/?3

Hãy thử trực tuyến!

Cuối cùng, mọi thứ trở nên dễ dàng hơn tôi nghĩ và không có nhiều chỗ để chơi gôn. Chương trình ban đầu tôi chặn là:

>ii:0)?\S:0)?\:*S:*+'PA@
3%4A|'S/!   S/;$=

Tôi đã chơi xung quanh với cố gắng để so sánh cả hai đầu vào cùng một lúc (mà lưu tất cả của một 1 byte), nhưng khi mà giọt vào "một trong số họ là không" phần, không có ở đó một cách tốt để con ra mục là khác không để thực hiện kiểm tra lần cuối, ít hơn một cách để làm điều đó mà không tốn ít nhất 1 byte (không tiết kiệm tổng thể).


1

Toán học, 149 Nhân vật

If[a==0,#[[3]]&&Mod[Abs@b,4]==3,If[b==0,#[[2]]&&Mod[Abs@a,4]==3,#[[1]]]]&[(q=#;Total[Boole@IntegerQ[q/#]&/@Range@q]<3&&q!=0)&/@{a^2+b^2,Abs@a,Abs@b}]

Mã này không sử dụng bất kỳ tính năng số nguyên tố chuẩn nào của mathicala, thay vào đó, nó đếm số lượng số nguyên trong danh sách {n / 1, n / 2, ..., n / n}; nếu số là 1 hoặc 2, thì n là số nguyên tố. Một hình thức chi tiết của chức năng:

MyIsPrime[p_] := (q = Abs@p; 
  Total[Boole@IntegerQ[q/#] & /@ Range@q] < 3 && q != 0)

Phần thưởng của tất cả các số nguyên tố Gaussian từ -20 đến 20:

Âm mưu của số nguyên tố gaussian



0

Con trăn - 117 122 121

def f(a,b):
 v=(a**2+b**2,a+b)[a*b==0]
 for i in range(2,abs(v)):
  if v%i<1:a=b=0
 return abs((a,b)[a==0])%4==3or a*b!=0

Vì 3 là số lớn nhất có thể là mod 4, bạn có thể thay thế ==3bằng>2
FlipTack
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.