is_gaussian_prime(z)?


23

任务

编写一个函数,该函数接受a,b代表高斯整数z = a+ib(复数)的两个整数。程序必须根据a+ib高斯素数来返回true或false 。

定义:

a + bi 当且仅当满足以下条件之一时,它是高斯素数:

  • ab均为非零且a^2 + b^2为素数
  • a是零,|b|是素数,|b| = 3 (mod 4)
  • b是零,|a|是素数,|a| = 3 (mod 4)

细节

您应该只编写一个函数。如果您的语言没有函数,则可以假定整数存储在两个变量中,然后打印结果或将结果写入文件。

您不能使用语言的内置功能,例如isprimeprime_listnthprimefactor。最低字节数获胜。程序必须a,ba^2+b^232位(带符号)整数的where 处工作,并且结束时间不应超过30秒。

首要清单

点表示高斯平面上的质数(x=实数,y=虚轴):

在此处输入图片说明

一些较大的素数:

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

2
我们是否可以使用分解函数(factor在Bash mfmFCJam中,...)

哦,不,我忘了存在那些分解方法,不,请不要=)并且32位限制适用于a ^ 2 + b ^ 2,否则就没有意义。感谢您的投入!我更新了问题。
瑕疵的

2
我在帖子中添加了高斯素数的定义。如果您不喜欢我的方法,请随时将其回滚,但是我绝对建议您在其中包含定义。
地下

太好了,我原本只是不想直接指出如何确定原始性以便人们有创造力=)
虚假的

1 1073741857在我看来不是高斯素数,因为1 ^ 2 + 1073741857 ^ 2是一个偶数...
RosLuP

Answers:


4

Haskell的- 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以下的所有数字进行幂运算,以检查其是否为质数。

非高尔夫版本:

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)

这使用Eratosthenes的筛子来计算所有素数的无限列表(在代码中称为l的列表)。(无限列表是haskell的众所周知的技巧)。

如何有一个无限的列表?在程序开始时,列表未评估,计算机没有存储列表元素,而是存储了计算它们的方法。但是当程序访问列表时,它会根据请求进行部分评估。因此,如果程序要请求列表中的第四项,则计算机将计算尚未评估的所有素数到第四,并将其存储,其余的将保持未评估状态,作为计算一次的方式存储需要。

请注意,所有这些都是由Haskell语言的懒惰特性自由提供的,从代码本身来看,这些都不是显而易见的。

程序的两个版本均已重载,因此它们可以处理任意大小的数据。


根据我的计算,您的第一个解决方案实际上是77个字符:D
致命的2014年

我数了换行符,不是吗?
骄傲的haskeller 2014年

我数了74个常规字符和3个换行符
2014年

您是对的,似乎出于某些原因,notepad ++在换行符之前添加了字符。谢谢!
骄傲的haskeller 2014年

这就是为什么我使用崇高的;)乐于助人!
2014年

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是高斯素数,则Gab)返回非零(true),否则返回零(false)。

它将整数素数测试折叠成n/d/d|n<2隐藏在返回值计算中的表达式。该代码还可以a*b替代a&&b(换句话说a!=0 && b!=0)和其他涉及运算符优先级和整数除法的技巧。比如n/d/d是说的更短的方式n/d/d>=1,这是说的溢出安全的方式n>=d*dd*d<=n或本质d<=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));}

功能:

  • 如果n为素数,则Qn)返回0(false),如果n为非素数,则返回1(true)。它是Gab)的辅助函数。

  • 如果a + bi是高斯素数,则Gab)返回1(true),否则返回0(false)。

样品输出(按比例放大200%)用于| 一个 |,| b | ≤128:

Sample128


2
+1图片!您是否也可以在第一个象限中做一个大约相同的大小(因为对称),在这里看起来真的很棒=)
更加虚假的2014年

您可以通过替换d = 2; for(; n / d / d && n%d; d ++);来保存几个字符。与for(d = 2; n / d / d && n%d ++;);
Alchymist 2014年

@Alchymist —确实可以保存字符,但是会产生错误的结果。重要的是,d++不要将这种情况作为条件的一部分发生,否则会弄乱后面的逻辑。另外,d=2for循环内部移动实际上会增加字符数,而不是减少字符数,因为d仍然需要intfor循环之前声明字符数。我想念什么吗?
托德·雷曼

太正确了。远离编码环境并且不够紧密地看待这一点的危险。增量必须保持原样,而初始化只会帮助您解决原始问题。如果在函数外部声明n&d而不指定int并将它们初始化为for循环,则可以节省很多资金,但是我认为您正在使函数自包含,这是对要求的严格解释。
Alchymist 2014年

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个字节。-2个字节,因为使用了火车而不是dfn。由于使用了警卫condition: if_true ⋄ if_false而不是,因此感谢ngn --4个字节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

调用为ghci ./gprimes.hs,然后可以在交互式外壳程序中使用它。注意:负数是挑剔的,必须放在括号中。即

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

3

Python- 121120个字符

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

p检查是否abs(x)是通过从2迭代的所有数字至原abs(x)**.5(这是sqrt(abs(x)))。它通过x % s让每个产生sall然后检查所有产生的值是否均为非零,并在遇到除数时停止生成值x。在中f,由@killmous的Haskell答案启发f(b,a)替换的情况。b==0


-1 char和来自@PeterTaylor的错误修正


很高兴能为您提供帮助:)
2014年

你可以替换s<abs(x)**.5使用s*s<abs(x)的是2的节约。虽然真的,你应该检查<=,所以它目前可能马车。
彼得·泰勒

@PeterTaylor感谢您指出错误...
2014年

用我的翻译打电话给f(0,15)yields TypeError: unsupported operand type(s) for &: 'bool' and 'generator'。:(
Falko 2014年

f(0,15)False在2.7.6和3.4.1(在OS X上)上为我提供了。您使用的是什么版本?
2014年

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


flambda也是不必要的,与list调用一起。没有这些的257个字节,加上一些空格删除。不过,这也许不再那么有效了
乔·金

(15,0)现在为257字节版本是正确的,运行时间也增加了5.5s,抱歉
Alexey 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除数(即余数)来检查是否为质数,然后另外检查一下,如果其中一个数字为零,则另一个数字等于3模4。默认情况下,返回值是其最后一行的值,如果满足所有条件,则这些条件将返回一些真实值。


我无法使其适用于负参数。
2014年

1
@killmous,您说得对,只是解决了
Tal

你可以解释一下算法吗?
自豪的haskeller 2014年

1
真好!顺便说一句,我认为您可以通过写$a%4>2而不是来消除几个字符$a%4==3
托德·雷曼

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。

一个非高尔夫的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))

通过插入tonumber(io.read())作为最后的参数,您可以节省6个字符g,而通过删除换行符可以节省2个字符
mniip 2014年

@mniip:不计算换行符,我只是为了清楚起见添加了换行符(没有横向滚动)。稍等片刻,我将更新读入的g。谢谢!
凯尔·坎诺斯

那么它仍然可以在合理的时间内大量使用吗?我primarly想过在检查所有高斯整数的方式暴力破解a其中|a| <= |z|如果a | z(如果a分歧z)。
瑕疵的

@flawr:我用a = 2147483644,b = 896234511进行了测试,并在约0.002 s内得到了0。我还用2147483629和2147483587(两个非常大的素数)对其进行了测试,并在另外0.002 s内得到了0。我正在尝试寻找一个大的数字对,使得a ^ 2 + b ^ 2是质数,并确保我有一个适用于大数字的解决方案。
Kyle

@flawr:经过a = 4600和b = 5603(a ^ 2 + b ^ 2 = 2147393609是质数和<2 ^ 32-1)测试,返回1花费了相同的0.002秒。
Kyle Kanos 2014年

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

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

该代码不使用mathematica的任何标准素数功能,而是对列表{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,你可以更换==3>2
FlipTack
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.