is_gaussian_prime (z)?


23

직무

a,b가우스 정수 z = a+ib(복소수) 를 나타내는 두 정수를 허용하는 함수를 작성하십시오 . 이 프로그램은 참 또는 거짓 여부에 따라 반환해야합니다 a+ibA는 가우스 주요 여부 .

정의:

a + bi 다음 조건 중 하나를 충족하는 경우에만 가우스 소수입니다.

  • a그리고 b모두 제로하고 a^2 + b^2소수
  • a0, |b|소수입니다|b| = 3 (mod 4)
  • b0, |a|소수입니다|a| = 3 (mod 4)

세부

함수 만 작성해야합니다. 언어에 함수가없는 경우 정수가 두 변수에 저장되어 있다고 가정하고 결과를 인쇄하거나 파일에 쓸 수 있습니다.

isprimeor prime_list또는 nthprimeor 와 같은 언어의 내장 기능을 사용할 수 없습니다 factor. 가장 적은 바이트 수가 이깁니다. 프로그램은 32 비트 (부호있는) 정수인 a,b곳에서 작동 a^2+b^2해야하며 30 초를 넘지 않아야합니다.

프라임리스트

점은 가우스 평면의 소수를 나타냅니다 ( x= 실수, y= 허수).

여기에 이미지 설명을 입력하십시오

더 큰 소수 :

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

2
우리는 인수 분해 기능을 사용할 수 있습니까 ( factorBash mfmFCJam, ...)

아뇨, 나는 그 인수 분해 방법이 존재하지 않았다는 것을 잊어 버렸습니다. 아니면 안됩니다 =) 그리고 32 비트 제한은 a ^ 2 + b ^ 2에 적용됩니다. 그렇지 않으면 의미가 없습니다. 입력 해 주셔서 감사합니다! 질문을 업데이트했습니다.
flawr

2
게시물에 가우시안 소수 정의를 추가했습니다. 내가 한 방법이 마음에 들지 않으면 자유롭게 롤백하지만 정의를 어딘가에 포함시키는 것이 좋습니다.
undergroundmonorail

좋은 점은 원래 사람들이 창의성을 발휘하기 위해 우선 순위를 결정하는 방법을 직접 지적하고 싶지 않았기 때문입니다.)
flawr

1 1073741857은 1 ^ 2 + 1073741857 ^ 2가 하나의 짝수이기 때문에 가우시안 프라임이
아닙니다

답변:


4

하스켈 - (77) / 108 107 숯을

사용법 : 두 솔루션 모두에서 a % b를 입력하면 a + bi가 가우스 소수인지 여부를 반환합니다.

내가 관리하는 가장 낮지 만 창의력이나 성능이 없습니다 (77 자)

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

이 솔루션은 n 이하의 모든 숫자를 통해 소수인지 확인합니다.

ungolfed 버전 :

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)

다음 솔루션에는 메모 기능이라는 추가 기능이 있습니다. 정수 n이 소수인지 확인한 후에는 컴퓨터에 저장되므로 n보다 작거나 같은 모든 숫자의 "프라이 머리"를 다시 계산할 필요가 없습니다.

(107 자. 코멘트는 명확성을위한 것입니다)

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

ungolfed 버전 :

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)

이것은 Eratosthenes의 체를 사용하여 모든 소수의 무한 목록을 계산합니다 (코드에서 목록으로 l이라고 함). (무한 목록은 잘 알려진 속임수입니다).

무한 목록을 어떻게 가질 수 있습니까? 프로그램이 시작될 때 목록은 평가되지 않고 목록 요소를 저장하는 대신 컴퓨터가 목록을 계산하는 방법을 저장합니다. 그러나 프로그램이 목록에 액세스하면 요청에 따라 부분적으로 자체 평가됩니다. 따라서 프로그램이 목록의 네 번째 항목을 요청하는 경우 컴퓨터는 아직 평가되지 않은 모든 소수를 계산하고 저장하며 나머지는 평가되지 않은 상태로 유지하여 한 번 계산하는 방식으로 저장합니다 필요합니다.

이 모든 것은 하스켈 언어의 게으른 특성에 의해 자유롭게 주어 지지만, 코드 자체에서 그 어느 것도 분명하지 않습니다.

프로그램의 두 버전이 모두 오버로드되어 임의 크기의 데이터를 처리 할 수 ​​있습니다.


내 카운트에 따르면, 첫 번째 해결책은 실제로 77 자입니다 : D
killmous

줄 바꿈을 세지 않습니까?
자랑스런 Haskeller

나는 정규 문자 74
개와

당신이 맞아요, 어떤 이유로 notepad ++가 개행 앞에 문자를 추가하는 것 같습니다. 감사!
자랑스런 Haskeller

그것이 내가 숭고한 사용하는 이유입니다.
killmous

9

C, 149118

편집 된 버전 (118 자) :

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

이것은 단일 기능입니다.

  • a + bi 가 가우스 소수 이면 G ( a , b )는 0이 아닌 값 (true)을 반환 하고 그렇지 않으면 0 (false)을 반환합니다.

정수 우선 순위 테스트를 n/d/d|n<2리턴 값 계산에 숨겨진 표현식으로 접습니다 . 이 골프 코드는 또한 연산자 우선 순위 및 정수 나누기와 관련된 다른 트릭 ( 즉, )을 a*b대체합니다 . 예를 들어 말하는 짧은 방법입니다 말하는 오버 플로우 - 안전한 방법이다, 또는 또는 본질적으로 .a&&ba!=0 && b!=0n/d/dn/d/d>=1n>=d*dd*d<=nd<=sqrt(n)


원본 버전 (149 자) :

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

기능 :

  • Q ( n )은 n 이 소수 이면 0 (거짓)을 반환 하고 n 이 프라임이 아닌 경우 1 (참)을 반환 합니다. G ( a , b ) 의 도우미 함수입니다 .

  • a + bi 가 가우스 소수 이면 G ( a , b )는 1 (true)을 반환 하고 , 그렇지 않으면 0 (false)을 반환합니다.

에 대한 샘플 출력 (확대 200 %) | |, | b | ≤ 128 :

샘플 128


2
이미지 +1! 당신은 또한 단지 제 1 사분면에 같은 크기 하나를 수행 할 수 (대칭 때문에), 정말 여기 멋지다 =)
flawr

d = 2; for (; n / d / d && n % d; d ++);를 대체하여 몇 개의 문자를 저장할 수 있습니다. for (d = 2; n / d / d && n % d ++;);
Alchymist

@Alchymist — 실제로 문자를 저장하지만 잘못된 결과를 생성합니다. d++조건의 일부로 발생하지 않는 것이 중요합니다. 그렇지 않으면 다음 논리를 엉망으로 만듭니다. 또한 루프 d=2내부를 이동하면 for실제로 루프 이전 d과 같이 선언해야 하므로 실제로 문자 수를 줄이지 않고 증가시킵니다 . 뭔가 빠졌습니까? intfor
Todd Lehman

너무 사실입니다. 이것을 코딩 환경에서 멀리 바라보고 충분히 면밀하게 보지 못하는 위험. 증분은 원래 위치에 머물러 있어야하며 초기화는 원래 솔루션에만 도움이됩니다. int를 지정하지 않고 함수 외부에서 n & d를 선언하고 for 루프에서 초기화하면 분명히 절약 할 수 있지만 요구 사항을 엄격하게 해석하는 기능을 자체 포함하고 있다고 가정합니다.
Alchymist

1
여기의 주요 테스트 루프는 멋진 골프입니다! 그러나 | a |에 변수를 사용하여 리턴 유형 및 인수에 대해 int 유형 지정자를 삭제하여 훨씬 더 많은 비용을 절약 할 수 있습니다. + | b | 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;}97 문자로 나옵니다.
feersum

4

APL (Dyalog Unicode) , 36 47 48 49 47 43 28 바이트

두 개의 정수 배열을 가져 와서 a b명령문의 부울 값을 리턴합니다 a+bi is a Gaussian integer.

편집 : 가우시안 소수 정의를 잘못 이해했기 때문에 +11 바이트. 답을 다시 수정하여 +1 바이트. 세 번째 버그 수정에서 +1 바이트 dfn 대신 기차를 사용하여 -2 바이트 condition: if_true ⋄ if_false대신 가드를 사용하여 ngn 덕분에 -4 바이트 if_true⊣⍣condition⊢if_false. 조건이 다른 경우 전체 기차로 작성하는 완전히 다른 방법을 찾아 ngn 덕분에 -15 바이트

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

온라인으로 사용해보십시오!

설명

{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 자 (줄 바꿈 포함)

다음은 외부 모듈을 사용하지 않고 내가 얻을 수있는 한 골치 아픈 비교적 간단한 Haskell 솔루션입니다.

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

as를 호출 ghci ./gprimes.hs하면 대화식 쉘에서 사용할 수 있습니다. 참고 : 음수는 까다 롭고 괄호 안에 넣어야합니다. 즉

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

3

파이썬 - 121 개 120 문자

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

pabs(x)2에서 abs(x)**.5(즉, sqrt(abs(x))) 까지의 모든 숫자를 반복하여 소수 인지 확인합니다 . x % s각각에 대해 양보함으로써 그렇게 합니다 s. all그런 다음 생성 된 모든 값이 0이 아닌지 확인하고의 제수를 만나면 값 생성을 중지합니다 x. 에서가 f, f(b,a)의 경우 대체 b==0에 의해 영감을, @killmous '하스켈 대답.


@PeterTaylor의 -1 문자 및 버그 수정


:)
killmous

당신은 대체 할 수 s<abs(x)**.5와 함께 s*s<abs(x)정말 검사를해야하지만 2의 절약을 위해 <=이 현재 아마 버그, 그래서.
피터 테일러

@PeterTaylor 버그를 지적 해 주셔서 감사합니다 ...
hlt

통역사에게 전화를 f(0,15)합니다 TypeError: unsupported operand type(s) for &: 'bool' and 'generator'. :(
Falko

f(0,15)제공 False(OS X에) 2.7.6와 3.4.1에 모두 나를 위해. 어떤 버전입니까?
hlt

3

Python 2.7 , 341 301 253 바이트, 속도에 최적화

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

온라인으로 사용해보십시오!

#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))

감사합니다 : 40 +48- Jo King의 전체 골프


f람다는 함께, 또한 uneccesary입니다 list전화. 257 바이트 , 공백 제거. 이것은 아마도 더 이상 효율적이지 않을 것입니다
Jo King

(15,0)는 버전 바이트 257에 지금 사실과 런타임 미안, 너무 5.5s 증가
알렉세이 Burdin

2

펄 - 110 개 107 105 문자

연결된 정의를 올바르게 따르기를 바랍니다.

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

언 골프 드 :

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

누군가가 물었다 때문에 설명 : 내가 인수를 (읽기 @_) 및에 자신의 절대 값을 넣어 $a, $b함수가 않기 때문에, 자신의 기호를 필요가 없습니다. 기준의 각 숫자의 소수성을 테스트 필요하지만,이 숫자는 여부에 따라 $a또는 $b내가 가장 짧은 방법으로 표현하고 넣어하려고 제로입니다 $n. 마지막으로 $n2와 그 사이의 숫자가 나머지 부분 (그 grep...<2부분) 없이 나누는 숫자를 세어 소수 인지 확인한 다음 숫자 중 하나가 0이면 다른 하나는 3 모듈로 4와 같은지 확인합니다. 반환 값은 기본적으로 마지막 줄의 값이며, 이러한 조건은 모든 조건이 충족되면 일부 값을 반환합니다.


부정적인 매개 변수에는 작동하지 않습니다.
killmous

1
@killmous 당신이 맞아, 그냥 고쳐
Tal

알고리즘을 설명해 주시겠습니까?
자랑스런 Haskeller

1
좋은! 그건 그렇고, 당신은 $a%4>2대신 에 글을 써서 몇 글자를 깎을 수 있다고 생각합니다 $a%4==3.
Todd Lehman

2

golflua 147 (141)

위의 숫자는 다른 기능을보기 위해 추가 한 줄 바꿈을 무시합니다. 그렇게하지 않겠다는 주장에도 불구하고, 무차별 대입은 사건 내에서 소수를 해결합니다.

\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())))

true이면 1을, 그렇지 않으면 0을 반환합니다.

골치 아픈 루아 버전

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

당신은 결국에 tonumber(io.read())인수로 연결하여 6 문자를 저장할 수 있고 g, 줄 바꿈을 제거하여 2 문자를 더 저장할 수 있습니다
mniip

@ mniip : 줄 바꿈은 계산되지 않았고 명확성을 위해 추가했습니다 (옆으로 스크롤하지 않음). 조금만 일하면 읽기를 g 단위로 업데이트하겠습니다. 감사!
Kyle Kanos

여전히 많은 수의 합리적인 시간 내에 작동합니까? 내가 primarly 모든 가우스 정수를 확인하는 방법을 bruteforce에 대해 생각 a어디에 |a| <= |z|경우 a | z(있는 경우 a분할 z).
flawr

@ flawr : a = 2147483644, b = 896234511로 테스트했으며 약 0.002 초에 0을 얻었습니다. 또한 2147483629 및 2147483587 (두 개의 매우 큰 소수)로 테스트했으며 0.002 초에 0을 얻었습니다. 나는 a ^ 2 + b ^ 2가 소수 인 큰 숫자 쌍을 찾으려고 노력하고 있으며 그러한 큰 숫자에 대한 효과적인 해결책을 얻었습니다.
Kyle Kanos

@flawr : a = 4600 & b = 5603 (a ^ 2 + b ^ 2 = 2147393609는 소수 & <2 ^ 32-1)으로 테스트되었으며 1을 반환하는 데 동일한 0.002 초가 걸렸습니다.
Kyle Kanos

1

APL (NARS), 99 자, 198 바이트

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}

테스트:

  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

룬 마법 , 41 바이트

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

온라인으로 사용해보십시오!

생각보다 훨씬 쉬워졌고 골프화의 여지가 많지 않았습니다. 내가 차단 한 원래 프로그램은 다음과 같습니다.

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

나는 두 입력을 동시에 비교하려고 노력했지만 (1 바이트 모두를 저장했습니다) "그중 하나가 0입니다"섹션으로 떨어질 때 어떤 항목 을 알아낼 수있는 좋은 방법이 없었습니다 마지막 검사를 수행하기 위해 0이 아니었고, 적어도 1 바이트를 소비하지 않고 수행 할 수있는 훨씬 적은 방법입니다 (전체 비용 절감).


1

수학, 149 자

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}]

이 코드는 수학의 표준 소수 기능을 사용하지 않고 {n / 1, n / 2, ..., n / n} 목록의 정수 수를 계산합니다. 숫자가 1 또는 2이면 n이 소수입니다. 정교한 형태의 기능 :

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

-20에서 20까지 모든 가우스 프라임의 보너스 플롯 :

가우스 소수의 음모



0

파이썬 - 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

3은 mod 4 일 수있는 가장 큰 숫자이므로 다음 ==3과 같이 바꿀 수 있습니다.>2
FlipTack
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.