是Mersenne Prime吗?


35

如果数字既是素数又可以以2 n -1的形式书写,则该数字就是梅森素数,其中n是正整数。

给定任何正整数,您的任务是确定它是否为梅森素数。您可以提交返回真实/错误值的函数,也可以提交执行IO的完整程序。

规则:

  • 因为这是,所以您应该以尽可能短的字节数为目标。允许内置。
  • 应用标准的高尔夫球漏洞-您无法从外部文件读取Mersenne素数,也无法将其硬编码到程序中。
  • 您的程序应能在您语言的标准整数大小范围内使用值。

测试用例

作为参考,可以在此处找到(已知)梅森素数的列表。一些方便的测试用例是:

2  -> False
1  -> False 
20 -> False
51 -> False
63 -> False

3    -> True
31   -> True
8191 -> True

祝大家圣诞快乐!祝您假期愉快,无论您庆祝什么:)


2
如果可以的话,我可以将它作为isprime挑战的伪装,因为它实际上并没有增加任何新内容。
瑕疵的2016年

9
@flawr它们非常相似-但是对于此挑战,内置函数的可能性较小,并且有很多有趣的方法来确定数字是否可表示为2^n-1
FlipTack

1
我相信梅森数的定义也要求n为素数(已经证明有必要(但不足以使(2 ^ n)-1为素数)。)
SuperJedi224 '16

4
@ SuperJedi224 n始终是素数,但是知道什么都没有改变,定义仍然是正确的。
FlipTack

2
@TheBitByte是的-如果您要实现某种基于概率的算法,这种算法在100%的时间内都无法正常工作,您仍然可以发布它,但它不会引起竞争:)
FlipTack

Answers:


19

果冻,5个字节

&‘<ÆP

在线尝试!

怎么运行的

&‘<ÆP  Main link. Argument: x

 ‘     Yield x+1.
&      Take the bitwise AND of x and x+1.
       This yields 0 iff x is a Mersenne number, i.e., iff x+1 is a power of 2.
   ÆP  Yield 1 if x is a prime, 0 if not.
  <    Compare the results to both sides,
       This yields 1 iff x is both a Mersenne number and a prime.

与Adnan的答案相同。见mothereff.in/byte-counter
凯利劳德

8
@KellyLowder该字节计数器使用UTF-8。Jelly和05AB1E均使用单字节字符集。
丹尼斯,

24

05AB1E,5个字节

二进制形式为2 n -1的正数仅包含1

码:

b`¹pP

说明:

b`      # Push each digit of the binary representation of the number onto the stack
  ¹p    # Check if the input is prime
    P   # Take the product of all these digits

使用CP-1252编码。在线尝试!验证所有测试用例


5
我想知道有人使用该技巧要多长时间:)
FlipTack

¹占用2个字节,所以这是6
凯利劳德

5
@KellyLowder是UTF-8。但是,05AB1E使用CP-1252编码而不是UTF-8编码。
阿德南(Adnan)

10

Python,45个字节

lambda n:-~n&n<all(n%i for i in range(2,n))<n

在线尝试!

怎么运行的

链接比较的三个术语

-~n&n<all(n%i for i in range(2,n))<n

请执行下列操作:

  • -~n&n计算n +1n的按位与。由于如果n是一个梅森数,则n仅由1个位组成,因此,当(且仅当)这种情况下,按位与将返回0

  • all(n%i for i in range(2,n))返回当且仅当N模我是非零对的所有值[2,...,N - 1] ,即,如果且仅当Ñ无正除数除了1Ñ

    换句话说,当且仅当n是一个复数,即n1或质数时,all都返回True

  • n 是不言自明的。

当且仅当单个比较执行相同时,链接比较才返回True

  • 因为所有返回任一 / 1 / 0-~n&n<all(n%i for i in range(2,n))只能返回,如果-~n&n产率0(即,如果Ñ是梅森数)和所有返回(即,如果Ñ或者1或素数)。

  • all(n%i for i in range(2,n))<n只要n> 1,该比较就成立,但是如果n = 1,则所有比较返回True,因此在这种情况下不成立。


1
哇,真是太神奇了:)
ABcDexter

8

Brachylog,7个字节

#p+~^h2

在线尝试!

Brachylog程序基本上是构成约束链的一系列约束条件:第一个约束条件在输入和匿名未知数之间(在此讨论中,我们将其称为A),第二个约束条件在该匿名未知数和第二个匿名未知数之间未知(我们称为B),依此类推。因此,该程序会像这样分解:

#p      Input = A, and is prime
+       B = A + 1
~^      B = X to the power Y, C = the list [X, Y]
h       D = the head of list C (= X)
2       D = 2

可以同时满足所有这些约束的唯一方法是,如果B是2的幂,即输入是2的幂减去1,并且输入也是素数。(Brachylog在内部使用约束求解器,因此该程序不会像评估顺序那样效率低下;它会在尝试表示为两个数字的幂之前会意识到它C的形式。)[2, Y]B

有趣的是,#p+~^ 几乎可以工作,因为梅森状素数只能使用2作为在非简并情况下(基证明),但a)其发生故障的非梅森素数 -1,因为它们可以表示为 ¹,和b )现有的Brachylog解释器似乎受到约束不严格的程序的迷惑(进入无限循环,或至少是长时间循环)。因此,在Brachylog中似乎不太可能击败7个字节。


给我留下深刻的印象!至于无限循环问题,这是由于谓词的重载。回顾过去,我认为我不应该对谓词实现任何重载。这也会导致诸如findall之类的问题。
Fatalize

7

Mathematica 26字节

PerfectNumberQ[# (#+1)/2]&

看到这个证明

只要没有奇数完美的数字,并且不存在已知的完美数字,就可以工作。


因此,您的答案被证明是无效的吗?
乔纳森·弗雷希

我认为空间是没有必要的。
乔纳森·弗雷希

@JonathanFrech n(n+1)/2只要n是梅森素数(欧几里得),该公式就会生成(偶数)个完美数。奇数是否可以具有形式n(n+1)/2,即为三角数,似乎是未知的。所有偶数都是三角形,在这里这n是梅森素数(Euler)。
杰普·斯蒂格·尼尔森

1
@JeppeStigNielsen问题是,使用未知事实作为解决方案的依据是否有效。
乔纳森·弗雷希

7

Mathematica,29 26字节

编辑:感谢马丁·恩德节省了3个字节

PrimeQ@#&&IntegerQ@Log2[#+1]&

PrimeQ@#&&1>BitAnd[#,#+1]&

我怀疑这会更快,因为前42个指数是硬编码的:

MersennePrimeExponentQ@Log2[#+1]&

6
PrimeQ@#&&1>BitAnd[#,#+1]&
马丁·恩德

5

Perl 6、29个字节

{.base(2)~~/^1*$/&&.is-prime}

试试吧

展开:

{             # bare block lambda with implicit parameter 「$_」

  .base(2)    # is its binary representation ( implicit method call on 「$_」 )
   ~~
  /^ 1* $/    # made entirely of 「1」s

  &&          # and

  .is-prime   # is it prime

}

由于Perl 6具有任意大的Ints,因此不会.base(2)0s 填充其前面。


5

Python,83 82 79 76 73字节

def f(m):
 s,n=(m!=3)*4,m>>2
 while-~m&m<n:s,n=(s*s-2)%m,n>>1
 return s<1

Python 2,71个字节

def f(m):
 s,n=(m!=3)*4,m/4
 while-~m&m<n:s,n=(s*s-2)%m,n/2
 return s<1

该函数实现了Lucas-Lehmer素数测试,因此虽然它不像其他Python产品那么短,但在处理大量输入时快得多。


这是在Python 2或Python 3上运行的一些测试代码。

from __future__ import print_function

def primes(n):
    """ Return a list of primes < n """
    # From http://stackoverflow.com/a/3035188/4014959
    sieve = [True] * (n//2)
    for i in range(3, int(n**0.5) + 1, 2):
        if sieve[i//2]:
            sieve[i*i//2::i] = [False] * ((n - i*i - 1) // (2*i) + 1)
    return [2] + [2*i + 1 for i in range(1, n//2) if sieve[i]]

def lucas_lehmer_old(p):
    m = (1 << p) - 1
    s = 4
    for i in range(p - 2):
        s = (s * s - 2) % m
    return s == 0 and m or 0

# much faster
def lucas_lehmer(p):
    m = (1 << p) - 1
    s = 4
    for i in range(p - 2):
        s = s * s - 2
        while s > m:
            s = (s & m) + (s >> p)
    return s == 0 or s == m and m or 0

def f(m):
 s,n=(m!=3)*4,m>>2
 while-~m&m<n:s,n=(s*s-2)%m,n>>1
 return s<1

# Make a list of some Mersenne primes
a = [3]
for p in primes(608):
    m = lucas_lehmer(p)
    if m:
        print(p, m)
        a.append(m)
print()

# Test that `f` works on all the numbers in `a`
print(all(map(f, a))) 

# Test `f` on numbers that may not be Mersenne primes
for i in range(1, 525000):
    u = f(i)
    v = i in a
    if u or v:
        print(i, u, v)
    if u != v:
        print('Error:', i, u, v)

输出

3 7
5 31
7 127
13 8191
17 131071
19 524287
31 2147483647
61 2305843009213693951
89 618970019642690137449562111
107 162259276829213363391578010288127
127 170141183460469231731687303715884105727
521 6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151
607 531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127

True
3 True True
7 True True
31 True True
127 True True
8191 True True
131071 True True
524287 True True

FWIW,这是一个稍微有效的版本,f它不会m在每个循环上都进行重新测试:

def f(m):
 s,n=m!=3and 4,m>>2
 if-~m&m<1:
  while n:
   s=(s*s-2)%m
   n>>=1
 return s<1

您可以将while循环全部写在一行上(不需要换行和缩进)
FlipTack

@FlipTack D'哦!谢谢!我真的不知道为什么,我错过了......我只注意到我可以刮掉一对夫妇更通过恢复到Python的2字节
PM 2Ring

4

R,41 40字节

matlab::isprime(x<-scan())&!log2(x+1)%%1

奇怪的是R中的内建函数mersenne接受n了参数,而不是2^n-1

x取自STDIN,使用matlab软件包检查它是否为质x+1数,并通过取mod 1并检查“非零”来检查2的对数是否为整数。

另外,如果您使用mersenne内置函数,则最终会略短一些,但感觉就像作弊:

numbers::mersenne(log2(scan()+1))

@Billywob节省了1个字节


发表了类似的答案,但我现在将其删除。我可以建议matlab::isprime保存一个字节。另外,您还必须使用<-功能内分配。
Billywob '16

@billywob刚刚还注意到,matlab :: isprime短了1个字节。(在您的解决方案上获得了1秒的峰值)。
2016年

您还可以使用log2(x+1)代替log(x+1,2)
Billywob


2

实际上,9个字节

;├╔'1=@p*

在线尝试!

说明:

由于形式为2 n -1的每个数字在其二进制表示形式中均具有全1,因此可以将梅森素数识别为具有该品质的素数。

;├╔'1=@p*
 ├╔'1=     only unique binary digit is 1
        *  and
;     @p   is prime

2

果冻,5个字节

@Dennis现有的5字节果冻答案的替代方法:

B;ÆPP

在线尝试!

怎么运行的:

B      Returns the binary representation of the input as a list [1, 0, 1, 1, ...]
 ;     And attach to this list 
  ÆP   a 1 if the input is a prime, 0 otherwise
    P  Calculates the product of this list of 1's and 0's

由于Mersenne Prime比2的幂小1,因此其二进制表示形式恰好是1。对于Mersenne素数,其输出为1,在所有其他情况下为0。


2

锡兰,66字节

Boolean m(Integer c)=>c>2&&c.and(c+1)<1&&!(2:c-2).any((d)=>c%d<1);

格式化(和注释):

// Check whether a (positive integer) number is a mersenne prime number.
//
// Question:  http://codegolf.stackexchange.com/q/104508/2338
// My Answer: http://codegolf.stackexchange.com/a/104805/2338

Boolean m(Integer c) =>
        // check whether c+1 is a power of two
        c.and(c+1)<1 &&
        // the standard primality check by trial division
         !(2 : c-2).any((d) => c%d < 1) &&
        // we need to exclude 1, which is unfortunately
        // matched by both criteria above, but is no prime.
        c>1;

通过作弊(将结果硬编码在Ceylon的Integer范围内),我们可以获得一个较短的字节(65):

Boolean h(Integer c) =>
        c.and(c+1)<1 && #20000000800a20ac.and(c+1)>0;

(似乎语法突出显示功能误解了锡兰的十六进制数字作为注释的开始。)

如果可以使用匿名函数,则该字节为49个字节:

[2,3,5,7,13,17,19,31,61].map((p)=>2^p-1).contains

2

Wolfram语言(Mathematica),23个字节

PrimeQ[BitAnd[#,#+2]#]&

在线尝试!

正确处理1是因为PrimeQ[BitAnd[1,1+2]*1] == PrimeQ@1 == False。否则,BitAnd[#,#+2]#要成为素数,我们需要#素数和BitAnd[#,#+2] == 1,这#是当梅森数时发生的。


做得很好!但是,作为从未使用过Mathematica的人,您的TIO代码起初令人困惑。然后,我意识到您正在将自己的功能与ngenisis的先前并列记录持有人进行比较。我认为最好仅显示函数的输出,并可能需要第二个链接将其与其他解决方案进行比较。
Deadcode

2

ECMAScript正则表达式,42 31字节

^(?!(xx+)\1+$)(x(x*)(?=\3$))+x$

^
(?!(xx+)\1+$)      # Assert that N is prime or 0 or 1.
(x(x*)(?=\3$))+x$  # Assert that N is a power of 2 minus 1 and is >= 3.
                   # The >=3 part of this prevents the match of 0 and 1.

在线尝试!

编辑:感谢尼尔,减少到31个字节。

基本的“是2的幂减去1”的测试是^(x(x*)(?=\2$))*$。这是通过循环操作“减去1,然后平均除以2”直到无法进行进一步处理,然后断言结果为零来进行的。通过将最后*一个更改为a +,可以强制循环至少迭代一次,可以将其修改为仅匹配≥1的数字。通过在循环中至少循环一次后得出的最终结果为1.,在最后一个值x之前插入一个$进一步修改它以使其仅匹配数字≥3。

相关的“是2的幂”检验是^((x+)(?=\2$))*x$格里米(Grimy)发现了一个匹配2减2的幂的简写:^((x+)(?=\2$)x)*$。这三个正则表达式的长度均相同。

替代的31字节版本,由Grimy撰写

^(?!(xx+)\1+$|((xx)+)(\2x)*$)xx

在线尝试!

# Match Mersenne primes in the domain ^x*$
^                   # N = input number
(?!                 # "(?!p|q)" is equivalent to "(?!p)(?!q)"; evaluate the
                    # logical AND of the following negative lookaheads:
    (xx+)\1+$       # Assert that N is prime or 0 or 1
|
    ((xx)+)(\2x)*$  # Assert that N is a power of 2 minus 1; this is based
                    # on "(?!(x(xx)+)\1*$)" which matches powers of 2.
)
xx                  # Assert that N >= 2, to prevent the unwanted match of
                    # 0 and 1 by both of the negative lookahead statements.

1
通过直接检查小于2的幂的数字1可以节省11个字节:在线尝试!
尼尔

@Neil非常感谢!我希望我会想到这一点,但是,那正是我想要发生的事情!
Deadcode

1
实际考虑会x(x+)(?=\3$)更有效吗?
尼尔

是的,您绝对正确。
Deadcode

2

正则表达式(ECMAScript),29个字节

^(?!(xx+|(x(x))+)(\1\3)+$)xxx

在线尝试!

聊天中受到Grimy的启发

正则表达式断言输入大于3,且输入形式都不是(xx+)\1+((xx)+)(\1x)+

第一个匹配复合数字。
第二个匹配的数字小于1,大于一个大于2的奇数的倍数。

01
2n1

由于2是唯一的比奇数素数小1的素数,因此负前瞻以及输入大于3的断言将仅匹配mersenne素数。


1

Ruby,47个字节

->b{!("%b"%(b/2)=~/0/||(2...b).find{|a|b%a<1})}


1

Python,65个字节

f=lambda n,i=3:(n^i)-all(n%i for i in range(2,n))<0 or f(n,-~i|i)

通过退出代码输出。递归错误为False。对于True,没有错误。

怎么运行的

由于2^n-1二进制完全由1组成,因此下一个2^n-1数字可以由生成number|number+1

此函数通过递归地2^n-1检查每个数字以查看其是否为质数和输入等式来使用此功能。如果该数字不是mersenne质数,则python最终将引发错误,因为将超过最大递归深度。


1
如果我没记错的话,<0〜> 0>
乔纳森·弗雷奇

1

Pushy,7个字节

oBoIpP#

在线尝试!

充分利用了mersenne数字在其二进制表示形式中只有一个的事实:

oB      \ Pop input, push its binary digits.
  oI    \ Re-push the input
    p   \ Test its primality (0/1)
     P# \ Print the product of the stack

1当数字的二进制表示形式中没有零且其素数为时,堆栈乘积才会为True


1

Pyth,8个字节

&.AjQ2P_

验证所有测试用例。

Pyth,8个字节

<.&QhQP_

验证所有测试用例。


怎么样?

代码细目#1

&.AjQ2P_    Full program with implicit input.

      P_    Is Prime?
   jQ2      Convert the input to binary as a list of digits.
 .A         All the elements are truthy (i.e. all are 1).
&           Logical AND.
            Output implicitly.

这是如何运作的?

2 n -1形式的数字仅在以二进制形式编写时始终包含1。因此,我们测试其所有二进制数字是否均为1,以及是否为质数。

代码分解#2

<.&QhQP_    Full program with implicit input.

      P_    Is Prime?
    hQ      Input + 1.
 .&Q        Bitwise AND between the input and ^.
<           Is smaller than? I.e. The bitwise AND results in 0 and the primality test results in 1.
            Output implicitly.

这是如何运作的?

这将测试输入+ 1是否为2的幂(即,如果它是梅森数字),然后执行素数测试。在Python中,bool是的子类int,因此将true视为1并将falsy视为0。为了避免显式检查一个为0且另一个为1,我们使用<(因为我们只有1个这样的情况)比较它们的值。


1

Java 8,53 52 49字节

n->{int i=1;for(;n%++i>0;);return(n&n+1|i^n)==0;}

错误修正,并通过由于4个字节golfed @Nevay

说明:

在这里尝试。

n->{                // Method with integer parameter and boolean return-type
  int i=1;          //  Temp integer `i`, starting at 1
  for(;n%++i>0;);   //  Loop and increase `i` as long as `n` is divisible by `i`
  return(n&n+1|i^n) //  Then return if `n` bitwise-AND `n+1` bitwise-OR `i` bitwise-XOR `n`
          ==0;      //  is exactly 0
}                   // End of method

当前的解决方案true针对大于2的每个素数返回,不仅针对Mersenne素数,返回56个字节:n->{for(int i=2;i<n;n&=-n%i++>>-1);return(n&n+1)<1&n>2;}
Nevay

1
52个字节:n->{int i=1;for(;++i<n&n%i>0;);return(n&n+1|i^n)<1;}
Nevay

@Nevay谢谢。而且不确定测试用例为什么不包含不是mersenne素数的素数。我自己添加了它们,您的确是正确的。
凯文·克鲁伊森

1
49个字节:n->{int i=1;for(;n%++i>0;);return(n&n+1|i^n)==0;}
Nevay



0

Python,93字节

def f(a):
 for b in range(a):
  if(a+1==2**b and not[i for i in range(2,a)if a%i<1]):return 1

这段代码在Python 2和Python 3中都可以使用,因此我没有指定版本。


0

拍子76字节

(define(g m)(for/or((i m))(= m(-(expt 2 i)1))))(if(and(prime? n)(g n))#t #f)

取消高尔夫:

(require math)
(define(f n)
  (define (ispowerminus1 m)
    (for/or ((i m))
      (= m (-(expt 2 i)1))))
  (if (and (prime? n)
           (ispowerminus1 n))
      #t #f))

测试:

(f 1)
(f 2)
(f 20)
(f 51)
(f 63)
(f 3)
(f 31)
(f 8191)

输出:

#f
#f
#f
#f
#f
#t
#t
#t

0

PHP,53字节

for($i=$n=$argv[1];--$i&&$n%$i;);echo!($i-1|$n+1&$n);

接受命令行参数;打印1Mersenne素数,其他为空字符串。用运行-r

分解

for($i=$n=$argv[1];--$i&&$n%$i;);   // loop $i down from $n-1 until $i divides $n
                        // If $n is prime, loop ends with $i=1. ($n=1 -> $i=0)
echo!($i-1|$n+1&$n);    // If $i!=1, $n is not prime. If ($n+1&$n)>0, $n is not Mersenne.
                        // If either $i-1 or $n+1&$n is truthy, the negation will be false.

0

C,94个字节

g(n,i){return--i?g(2*n,i):n;}n,r;f(x){for(n=r=1;++n<x;)r=x%n?x^g(2,n)-1?r:r|2:r&2;return r>2;}

如果数字是Mersenne Prime,则返回1,否则返回0。


建议~x+g(2,n)而不是x^g(2,n)-1
ceilingcat

0

Scala,59字节

def f(t:BigInt)=t.isProbablePrime(t.bitLength*9)&(1+t)%2==0

此函数要求输入为BigInt。您可以轻松地将字符串“ 162259276829213363391578010288127”(2 ** 107-1是Mersenne质数)转换为BigIntby BigInt("162259276829213363391578010288127")isProbablePrime()顾名思义,它可能会出错。但是概率不大于0.5^(t.bigLength)*9

独立脚本版本为72个字节长。

val t=BigInt(args(0));print(t.isProbablePrime(t.bitLength*9)&(1+t)%2==0)

假设我们将其保存为“ t.scala”,则程序可以运行为

>scala t.scala 162259276829213363391578010288127
>true

如果Scala具有功能ProbableisProbablePrime则可以从中删除isPrime
MilkyWay90

0

Perl 5,53个字节

52个字节的代码+ 1个 -p

$f=0|sqrt;1while$_%$f--;$_=!$f*(sprintf'%b',$_)!~/0/

在线尝试!


根据元共识,该-p语言被归类为另一种编程语言,因此不计入您的字节数。
MilkyWay90
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.