is_gaussian_prime(z)?


23

仕事

a,bガウス整数z = a+ib(複素数)を表す2つの整数を受け入れる関数を作成します。プログラムa+ibは、ガウス素数であるかどうかに応じてtrueまたはfalseを返す必要があります。

定義:

a + bi 次の条件のいずれかを満たす場合にのみ、ガウス素数です。

  • aそしてb、両方とも非ゼロでa^2 + b^2あり、素数です
  • aゼロ、|b|素数、|b| = 3 (mod 4)
  • bゼロ、|a|素数、|a| = 3 (mod 4)

詳細

関数のみを記述する必要があります。言語に関数がない場合、整数が2つの変数に格納されていると仮定して、結果を出力するか、ファイルに書き込むことができます。

isprimeor prime_listnthprimeorなどの言語の組み込み関数は使用できませんfactor。最も少ないバイト数が優先されます。プログラムは、32ビット(符号付き)整数a,bである場所で動作する必要がa^2+b^2あり、30秒以内に終了するはずです。

プライムリスト

ドットはガウス平面上の素数を表します(x=実数、y=虚数軸):

ここに画像の説明を入力してください

いくつかのより大きな素数:

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

2
因数分解関数を使用することは許可されていますか(factorBash mfおよびmFCJamで...)

ああ、いや、それらの因数分解法が存在することを忘れていた、いやしないでください=)そして、32ビット制限はa ^ 2 + b ^ 2に適用され、そうでなければ意味がありません。ご意見ありがとうございます!質問を更新しました。
flawr 14

2
ガウス素数の定義を投稿に追加しました。私のやり方が気に入らなければ、遠慮なくロールバックしてください。しかし、どこかに定義を含めることをお勧めします。
地下

いいですね、元々は、人々が創造力を
発揮

1 1073741857は1 ^ 2 + 1073741857 ^ 2が1つの偶数であるため、ガウスプライムではないようです...
RosLuP

回答:


4

ハスケル- 77/ 108 107文字数

使用法:両方のソリューションで、a%bと入力すると、a + biがガウス素数であるかどうかが返されます。

最下位のiが管理しているが、創造性やパフォーマンスはない(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未満のすべての数値を使用して、素数であるかどうかを確認します。

改変されていないバージョン:

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

改変されていないバージョン:

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)

これは、エラトステネスのふるいを使用して、すべての素数の無限リストを計算します(コードのリストではlと呼ばれます)。(無限リストはhaskellのよく知られたトリックです)。

無限のリストを持つことはどのように可能ですか?プログラムの開始時にリストは評価されず、リスト要素を保存する代わりに、コンピューターはそれらを計算する方法を保存します。しかし、プログラムがリストにアクセスすると、リクエストまで部分的に評価されます。したがって、プログラムがリストの4番目の項目を要求する場合、コンピューターはまだ評価されていない4番目までのすべての素数を計算して保存し、残りは評価されずに残り、一度計算する方法として保存されます必要です。

これはすべて、Haskell言語の怠thisな性質によって自由に与えられていることに注意してください。コード自体からは明らかです。

プログラムの両方のバージョンがオーバーロードされているため、任意のサイズのデータ​​を処理できます。


私のカウントでは、あなたの最初の解決策は実際には77文字です:D
killmous 14

改行を数えましたか?
誇りに思ってhaskeller 14

私は74の、通常の文字と3つの改行カウント
killmous

あなたは正しい、何らかの理由でnotepad ++が改行の前に文字を追加するようです。ありがとう!
誇りに思ってhaskeller 14

だから私は崇高なものを使う;)
殺害14

9

C、149の 118文字

編集版(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;}

これは単一の機能です。

  • G(、B)非ゼロ復帰(真)場合+ biはそうでなければ、ガウス素数、またはゼロ(偽)です。

整数の素数性テストを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));}

関数:

  • QNは)場合は0(false)を返しnは素数であるか、または1(真)であれば、Nノンプライムあります。これはGab)のヘルパー関数です。

  • G(、B)1(TRUE)を返した場合、A + biはそうでなければ、ガウス素数、または0(偽)です。

のサンプル出力(200%に拡大)| |、| b | ≤128:

Sample128


2
画像の+1!また、最初の象限でちょうど同じサイズの1つを行うことができますか(対称性のため)、ここでは本当に素晴らしいです=)
flawr 14

d = 2; for(; n / d / d && n%d; d ++);を置き換えることにより、数文字を保存できます。with(d = 2; n / d / d && n%d ++;);
アルキミスト14

@Alchymist —実際に文字は保存されますが、誤った結果が生成されます。d++条件の一部として発生しないことが重要です。そうでないと、後続のロジックが台無しになります。また、ループのd=2内側を移動すると、for実際には文字数が減少するのではなく増加します。ループの前にd宣言する必要があるためです。何か不足していますか?intfor
トッドリーマン14

本当だ。これをコーディング環境から遠ざけて見ると、十分ではありません。増分は現在の位置にとどまらなければならず、初期化は元のソリューションにしか役立ちません。intを指定せずに関数の外でn&dを宣言し、forループで初期化すると、明らかに節約されますが、要件の厳密な解釈である関数を自己完結させていると思います。
アルキミスト14

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 14

4

APL(Dyalog Unicode)36 47 48 49 47 43 28バイト

2つの整数の配列を受け取り、a bステートメントのブール値を返しますa+bi is a Gaussian integer

編集:ガウスプライムの定義を誤解したため、+ 11バイト。回答を再度修正してから+1バイト。3番目のバグ修正から+1バイト。dfnの代わりにトレインを使用するため、-2バイト。-4バイトはngnのおかげで、condition: if_true ⋄ if_false代わりにガードを使用しているためですif_true⊣⍣condition⊢if_false。condition-if-elseを完全なトレインとして記述するためのまったく異なる方法を見つけたため、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それぞれに譲歩することでそうしますsall次に、生成されたすべての値がゼロ以外であるかどうかを確認し、の約数に達すると値の生成を停止しますx。ではf@ killmousのHaskellの回答に触発されf(b,a)たのケースを置き換えます。b==0


-1文字と@PeterTaylorからのバグ修正


私は助けることができてうれしい:)
19:55に殺害14

あなたは置き換えることができs<abs(x)**.5s*s<abs(x)本当にあなたがチェックする必要があるが、2の節約のために<=、それが現在ではおそらくバグだらけですので、。
ピーターテイラー14

@PeterTaylorバグを指摘していただきありがとうございます...
hlt 14

呼び出しf(0,15)利回りTypeError: unsupported operand type(s) for &: 'bool' and 'generator'私の通訳付きを。:(
ファルコ14

f(0,15)False2.7.6と3.4.1(OS Xの両方)で私に与えてくれます。どのバージョンを使用していますか?
hlt 14

3

パイソン2.7341の 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- ジョーキングへのゴルフ全体


fラムダはと一緒に、またuneccesaryでlistコール。それらを含まない257バイト、およびいくつかの空白の削除。これはおそらくもう効率的ではありません
ジョーキング

(15,0)は、バージョンバイト257で今真実であると、実行時には申し訳ありませんが、あまりにも5.5S増加
アレクセイBurdin

2

Perlの- 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。最後に$n、2とそれ自身の間の数を剰余なしに分割することで素数であるかどうかを調べ(それがgrep...<2部分です)、さらに、数字の1つがゼロの場合、もう1つが4を法とする3に等しいことを確認します戻り値はデフォルトで最後の行の値であり、これらの条件はすべての条件が満たされた場合に何らかの真理値を返します。


負のパラメーターでは機能しません。
殺害14

1
@killmouse正しい、ちょうどそれを修正した
タル14

アルゴリズムを説明してもらえますか?
誇りに思ってhaskeller 14

1
いいね!ところで、の$a%4>2代わりに書くことで、いくつかの文字を削ることができると思います$a%4==3
トッドリーマン14

2

ゴルフルア 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を返します。

無償のLuaバージョン、

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

あなただけ差し込むことによって6つの文字を保存することができますtonumber(io.read())への引数としてg改行を除去することにより、複数のエンドに、そして2
mniip

@mniip:改行はカウントされません。わかりやすくするために追加しました(横スクロールなし)。少し作業を始めたら、gのreadを更新します。ありがとう!
カイルカノス14

まあ、それはまだ多数の時間の合理的な時間内に動作しますか?私はprimarlyすべてのガウス整数をチェックする方法でbruteforcing考えたaどこ|a| <= |z|かのa | z(場合a除算z)。
flawr

@flawr:a = 2147483644、b = 896234511でテストし、約0.002秒で0になりました。また、2147483629および2147483587(2つの非常に大きな素数)でテストし、さらに0.002秒で0になりました。私はa ^ 2 + b ^ 2が素数になるような大きな数のペアを見つけようとし、そのような大きな数に対して有効な解決策があることを確認しています。
カイルカノス14

@flawr:a = 4600&b = 5603(a ^ 2 + b ^ 2 = 2147393609は素数&<2 ^ 32-1)でテストされ、1を返すのに同じ0.002秒かかりました。
カイルカノス14

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バイトすべてを保存しました)が、それが「そのうちの1つがゼロ」セクションに落ちたとき、どの項目を見つけるのが良い方法がありませんでした最後のチェックを実行するためにゼロ以外でしたが、少なくとも1バイトを費やすことなくそれを行う方法はほとんどありません(全体的な節約はありません)。


1

Mathematica、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が最も大きいので数は、置き換えることができ、4 MOD可能==3>2
FlipTack
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.