找到第N对双素数


26

如果两个质数相差两个,则被定义为双质数。例如,3和5是双素数,29和31也是双素数。

编写一个程序,查找第n对孪生素数(其中n来自STDIN)并将其打印在STDOUT上,并用逗号和空格分隔。这是代码高尔夫球,因此最短的代码获胜。

输入样例:

3

样本输出:

11, 13

5
等等...用户将输入第n对孪生素数,您要我们输出吗?那么,仅回显用户输入的内容吗?;-)
Iszi 2014年

嗯...那句话有点尴尬!:P
Jwosty 2014年

Answers:


11

哈斯克尔118

main=putStrLn.(!!)[show n++", "++show(n+2)|n<-[2..],all((>0).rem n)[2..n-1],all((>0).rem(n+2))[2..n]].(+)(-1)=<<readLn

蛮力所有孪生素数,并打印所述n 对。


5
好东西!通过分离过滤功能并使用interact代替,putStrLn您可以走得更远,并将其降低到105:a#b=all((>0).rem a)[2..a-b];main=interact$(!!)[show n++", "++show(n+2)|n<-[2..],n#1,(n+2)#2].(+)(-1).read
Flonk 2014年

10

CJam,29 26字节

Y4]{{:)_{mp}/&!}g}q~*", "*

在线尝试。

例子

$ for i in {1..10}; do cjam twin-primes.cjam <<< $i; echo; done
3, 5
5, 7
11, 13
17, 19
29, 31
41, 43
59, 61
71, 73
101, 103
107, 109

怎么运行的

Y4]        " Push [ 2 4 ].                                                            ";
{          "                                                                          ";
  {        "                                                                          ";
    :)     " Increment each integer in the array.                                     ";
    _      " Duplicate the array.                                                     ";
    {mp}/  " For each integer in the array, push 1 if it's prime and 0 otherwise.     ";
    &!     " Compute the logical NOT of the bitwise AND of the two previous integers. "; 
  }g       " If the result is non-zero, repeat the loop.                              ";
}q~*       " Do the above “N” times, where “N” is the integer read from STDIN.        ";
", "       " Join the array by comma and space.                                       ";

9

Perl,101 87

87个字符,建立在aschepler的评论之上

$n=pop;$r='^1$|^(11+?)\1+$';($t=1x$s)=~$r||"11t"=~$r||--$n||die"$s, ",$s+2,$/while++$s

101个字符,较早的答案

$n=pop;$r=qr/^1$|^(11+?)\1+$/;(1x$s)!~$r&&(1x($s+2))!~$r&&++$i==$n&&say($s,", ",$s+2)&&exit while++$s

用法:

$ perl ./twin_primes.pl 10
107, 109

说明

$n = pop;                 # Pulls twin prime pair counter from @ARGV
$r = qr/^1$|^(11+?)\1+$/; # The money line - a regex that verifies
                          # if a string of 1's has non-prime length

while ( ++$s ) {          # Loop over integers

                          # '&&' short-circuits
    (1 x  $s    ) !~ $r   # Negated regex match evaluates to true if $s is prime
 && (1 x ($s+2) ) !~ $r   # Same for $s + 2
 &&          ++$i == $n   # Counter to control which pair to print
 && say( $s, ", ", $s+2 ) # Print the line
 && exit                  # Terminate program
}

非素数正则表达式的工作原理在此SO问题中进行了说明


..这是什么?
seequ 2014年

@TheRare:它使用正则表达式来检查数字的素数。
扎伊德2014年

1
你让我震惊。+1。
seequ 2014年

@TheRare:我添加了一个解释为什么起作用的原因。我确定仍有改进的空间:)
Zaid 2014年

2
我几乎会做的。有几个剃过的角色:$n=pop;$r='^1$|^(11+?)\1+$';($t=1x$s)=~$r||"11$t"=~$r||--$n||exit say("$s, ",$s+2)while++$s
aschepler 2014年

8

C:113

n,c,l;main(i){for(scanf("%d",&n),l=2;n;l=c==i?n-=i==l+2,i:l,i+=2)for(c=2;c<i&&i%c++;);printf("%d, %d\n",l-2,l);}

样品运行:

$ for i in $(seq 1 10); do echo $i | ./twinprimes; done
3, 5
5, 7
11, 13
17, 19
29, 31
41, 43
59, 61
71, 73
101, 103
107, 109

感谢Dennis,bebe和Alchymist的帮助。


您可以使用scanf代替命令行参数来节省一些字节。另外,o=0由于o是全局的,因此不必要。
丹尼斯

main可以包含一个默认的int变量,在赋值和语句之间递增c以及i在赋值和语句之间可以缩短代码,l可以将的赋值返回给for循环的第三个块,因此您无需大括号,并且在printf中仅使用一个分隔符肯定可以使它更紧凑。
贝贝2014年

谢谢,贝贝!我注意到我也有c<=i-1,这很愚蠢。
millinon 2014年

我不明白的方式,通过增加剃一个字节il赋值表达式,因为的(新)值i是用来递减n。有小费吗?
millinon 2014年

如果我没记错的话,有一个地方可以增加i,但是我相信它的编译器依赖性:(
bebe 2014年

6

果酱-26

1e4,{mp},_2f-&qi(=_2+", "\

适用于小于10000的素数;您可以将4较大的数字替换为较高的指数(可能最多10 20),但是该程序会变慢,并且会占用更多内存。

http://cjam.aditsu.net/上尝试

说明:

1e4,创建数组[0 1 2 ... 9999]
{mp},仅选择素数
_2f-复制该数组,并从每个项目中减去2
&与两个数组相交,从而从每个双素数对中找到较低的素数,
qi读取输入并将其转换为整数以
(=调整索引并从数组中获取相应的(较低的)孪生素数
_2+复制素数并加2
", "\放置两个素数之间的逗号和空格


4

Mathematica-63个字符

Print[#-2,", ",#]&@Nest[NestWhile[NextPrime,#,#2-#!=2&,2]&,1,n]

笔记

实际上,这是一个相当简单的实现。缩短导致几乎没有混淆。

NextPrime 是一个内建函数,可找到数字后的下一个素数。

NestWhile[NextPrime,#,#2-#1!=2&,2]& 是一个匿名函数,用于查找数字后的下一个双素数对中的较大素数。

Nest应用此匿名函数n时间。

Print[#-2,", ",#]&是一个匿名函数,它根据规范输出到stdout。可悲的是,仅此一项就占用了63个字符的解决方案中的18个字符。

In[1]:= Do[                                                                     
         Print[#-2,", ",#]&@Nest[NestWhile[NextPrime,#,#2-#!=2&,2]&,1,n],
         {n, 1, 10}
        ]
3, 5
5, 7
11, 13
17, 19
29, 31
41, 43
59, 61
71, 73
101, 103
107, 109

更新: 重新实现此CJam解决方案可以节省两个字符。但是,此算法限制的最大值n。只需将Nest...零件替换为Intersection[#,#-2][[5]]&@Prime@Range[999]


您的STDIN在哪里?:)
mfvonh 2014年

4

Javascript(E6)92 96

更短且更合规-使用Spidermonkey Shell读取stdin / write stdout(带逗号和空格)。它会在一分钟内在我的PC上找到第10000个对1260989、1260991
可以使用p[n]=o=n代替来缩短p.push(o=n),从而使p数组稀疏。但这相当慢,而且无论如何我都不会赢得代码长度。

m=readline();for(n=3,o=p=[];m;n+=2)p.every(e=>n%e)&&(m-=n-o<3,p.push(o=n));print(o-2+', '+o)

要在firefox控制台中尝试:

m=prompt();for(n=3,o=p=[];m;n+=2)p.every(e=>n%e)&&(m-=n-o<3,p.push(o=n));alert(o-2+', '+o)

不打高尔夫球

找到所有前m个双胞胎的函数(返回最大值):

T=m=>{
  for (o=n=3, p=[2], t=[]; !t[m-1]; n+=2)
    p.every(e => n%e) && (n-o-2 ? 0 : t.push(n), p.push(o=n))
  return t
}

例: console.log(T(50))

[5, 7, 13, 19, 31, 43, 61, 73, 103, 109, 139, 151, 181, 193, 199, 229, 241, 271, 283, 313, 349, 421, 433, 463, 523, 571, 601, 619, 643, 661, 811, 823, 829, 859, 883, 1021, 1033, 1051, 1063, 1093, 1153, 1231, 1279, 1291, 1303, 1321, 1429, 1453, 1483, 1489]

只是最后一个:

L=m=>{
  for (o=n=3,p=[2]; m; n+=2)
    p.every(e => n%e) && (m -= n-o==2, p.push(o=n))
  return o
}

然后,接两行并添加IO

m = prompt()
for (o=n=3, p=[2]; m; n+=2)
  p.every(e => n%e) && (m -= n-o==2, p.push(o=n))
alert('o-2+', '+o)

4

J- 49 60 55 51字节

我决定采用一种简单的方法。函数t查找给定素数作为输入的下一个孪生素数(现在f函数中已包括)。函数f找到第n个孪生素数。这也是我用J编写的第一个实际程序。

f=:[:(":,', ',":@+&2)(4&p:(,{~-=2:)])^:_@>:^:(]`2:)

例子:

   f 1
3, 5
   f 2
5, 7
   f 3
11, 13
   f 4
17, 19
   f 5
29, 31
   f 100000
18409199, 18409201

只是为了一些眉毛,有非高尔夫版本。

twin =: (4&p:)(($:@[)`(,)@.(=(]+2:)))]
f    =: ((]-2:),])((0:{twin) ^: (]`(2:)))

说明:

f=:[:(":,', ',":@+&2)(4&p:(,{~-=2:)])^:_@>:^:(]`2:)
                     (4&p:(,{~-=2:)])^:_@>:^:(]`2:)
                                        @>:^:(]`2:)  main loop
                                           ^:(]`2:)  Repeat n times, starting with value of 2
                                        @>:          Add one to the current value and apply to the following function.
                     (4&p:(,{~-=2:)])^:_             Get the next twin prime
                                     ^:_             Recurse until there's no change
                          (,{~-=2:)                  If next prime - current value == 2, return current value, otherwise the next prime.
                      4&p:                           Get the next prime
     (":,', ',":@+&2)                                Format the output and add 2 to the second value.
   [:                                                Apply the twin prime to the formatter.

Basically, if n is 4, this creates a recursion tree like this:
 let T be the recursion inside t
 and numbers between rows the return values of according function
   (t * n) 3
-> (t * 4) 3
-> t  t  t  t  3
   17 11 5  3
-> (T  T) (T  T) T  T  3
    17 13  11 7  5  3
-> 17

为了符合规范,还需要做更多的工作:“将它们打印在STDOUT上,并用逗号和空格隔开”。当然,这与算法无关,但是确实会增加程序的长度。
Szabolcs

@Szabolcs更好吗?
seequ 2014年

当然,+ 1。J很酷。
Szabolcs

@Szabolcs确实是。虽然它使我迷惑不解。一直都变得更加轻松(这是我手工编写的第一个程序)。另外,谢谢。
seequ 2014年

4

C#,265

using System.Linq;class P{static void Main(string[] args){var i=int.Parse(args[0]);int f=0,c=0;for(int j=1;;j+=2){var b=(Enumerable.Range(1,j).Count(x=>j%x==0)==2);if(f==0 && b){f=j;continue;}if(b){c++;if(c==i){System.Console.WriteLine(f+","+j);break;}j-=2;}f=0;}}}

2
+1,但在打印mnumber时需要在逗号后添加一个空格
Cristian Lupascu 2014年

1
您可以再保存两个字符:.Count(x=>j%x==0)==2)->.Count(x=>j%x<1)<3)
Cristian Lupascu 2014年

2
同样,可以P代替调用您的类,Programa代替调用参数args
Cristian Lupascu 2014年

1
不会按原样进行编译- )结束后会有额外的费用.Count(...)<3。您也可以通过更改var i=int.Parse(args[0]);int f=0,c=0;为来节省一点时间int i=int.Parse(args[0]),f=0,c=0;。您可以通过从循环中提取初始化程序来进一步保存一些内容,因此c=0;for(int j=1;=> c=0,j=1;for(;
鲍勃

此外,完整重写for循环的主体,并使用完全限定的名称而不是using Systemusing System.Linq;class P{static void Main(string[]args){int i=int.Parse(args[0]),f=0,c=0,j=1;for(;;j+=2)if(Enumerable.Range(1,j).Count(x=>j%x<1)>2)f=0;else if(f<1)f=j;else{if(++c==i){System.Console.WriteLine(f+", "+j);break;}j-=2;f=0;}}},238个字符。
鲍勃


2

Perl,100 95

$n=<>;$i=3;while($c<$n&&($l=$i++)){$i++until!grep{$i%$_<1}(2..$i-1);$c++if$i-$l<3}print"$l, $i"

取消高尔夫:

$n = <>;          # Read from STDIN
$i = 3;           # Tiny hack because I know I don't need the number 2
while ($c<$n && ($l = $i++)) {   # $c counts the pairs, $l is the last prime
  $i++ until ! grep {$i%$_<1} (2..$i-1);   # Increase $i until it's not divisible by anything
  $c++ if $i-$l < 3   # If $i and $l are twin primes, count it
}
print "$l, $i"    # That damned comma added a whole character to my code!

2

T-SQL(2008+):344

蛮力迫使CTE查找素数,窗口函数计数n,然后通过联接查找孪生子。对于输出<1,000的输出,每秒可以工作,而对于输出<10,000的输出,则需要不到一分钟的时间。

打高尔夫球(这里是 SQLFiddle ):

WITH x(i) AS(SELECT 99 UNION ALL SELECT i-2
FROM x WHERE i>3),z AS(SELECT RANK()OVER(ORDER BY x.i)n,x.i
FROM x x LEFT JOIN x y ON x.i%y.i=0 AND y.i NOT IN(x.i,1)
WHERE y.i IS NULL)SELECT LTRIM(a)+', '+LTRIM(b)FROM(SELECT RANK()
OVER(ORDER BY x.i)n,x.i a,y.i b FROM z x,z y WHERE x.n=y.n-1
AND x.i=y.i-2) o WHERE n=3
OPTION(MAXRECURSION 0)

清晰:

WITH x(i) AS (
   SELECT 99
    UNION ALL
   SELECT i-2
   FROM x
   WHERE i > 3
)
,z AS (
SELECT RANK()OVER(ORDER BY x.i)n,x.i
FROM x x
WHERE NOT EXISTS
  (SELECT *
   FROM x y
   WHERE x.i%y.i = 0
    AND y.i NOT IN (x.i,1)
  )
)
SELECT LTRIM(a)+', '+LTRIM(b)
FROM (
    SELECT RANK()OVER(ORDER BY x.i)n,x.i a, y.i b
    FROM z x, z y
    WHERE x.n = y.n+1
    AND x.i = y.i+2
) o
WHERE n = 3
OPTION(MAXRECURSION 0)

1

高尔夫脚本46

~[1 3]\{\{))}%.{:x,{)x\%!},,2=}/*@\-.}do;', '*

在线测试:链接

带注释的代码:

~                       # parse the input as an int
[1 3]                   # add the array [1, 3] on the stack
\                       # invert the items on the stack
{                       # begin loop
  \                     # bring the array to the top of the stack
  {))}%                 # add 2 to each of the numbers in the array
  .{:x,{)x\%!},,2=}/    # check if numbers are prime (leaves a 0 or 1 for both numbers on the stack)
  *                     # multiply the two 0/1 numbers (will only get 1 if both are 1)
  @\-                   # subtract the result from the inital int
  .                     # copy the new int value on the stack to be consumed by the 'do' loop
}do                     # repeat until the initial int was taken down to 0
                        # at this point the array contains the two numbers we're looking for
;                       # get rid of the 0 from the stack
', '*                   # format the output

1

PHP 5.4、223

不是一个较小的,而是从php尝试一下。

$n=$argv[1];function i($k){for($i=2;$i<=(int)($k/2);$i++)if($k%$i==0)return 0;return 1;}function t($t){return (i($t) && i($t+2))?1:0;}$g=1;$d=0;do{if(t($g)==1){if($d<$n){$d++;}else{print_r([$g,$g+2]);break;}}$g++;}while(1);

1

C 309

继续获取下一个素数,并存储奇数和偶数项,然后检查差异是否为两个。

int main()
{
int n;
scanf("%d",&n);
int a=2,b=3,k=2,q;
int odd=1;
int p;
if(n>0)
{
while(n)
{
k++;
p=1;
q=ceil(sqrt(k));
for(int i=2;i<=q;i++)
{
if(k%i==0)
{
p=0;
break;
}
}
if(p)
{
if(odd%2==0)a=k;
else b=k;
if(abs(a-b)==2)n--;
odd++;
}
}
}
printf("%d %d\n",a,b);
return 0;
}

1
请不要平方根! for (int i=2;i*i<=k;i++)
edc65 2014年

1

R,91个字符

a=scan();n=1;p=5;while(n!=a){p=p+1;q=p-2;if(sum(!p%%2:p,!q%%2:q)<3)n=n+1};cat(q,p,sep=", ")

没什么好看的:

a=scan()
n=1
p=5
while(n!=a){
    p=p+1
    q=p-2
    if(sum(!p%%2:p,!q%%2:q)<3) # Check that p and q are both primes by checking
       n=n+1                   # the number of zeroes resulting from 
}                              # p modulo each integers 2 to p and same for q
cat(q,p,sep=", ")

用法:

> a=scan();n=1;p=5;while(n!=a){p=p+1;q=p-2;if(sum(!p%%2:p,!q%%2:q)<3)n=n+1};cat(q,p,sep=", ")
1: 10
2: 
Read 1 item
107, 109


0

JavaScript(Node.js),162个字符

从stdin读取,输出到stdout,退出“ early”作为input <= 0

t=process.argv[2],c=0,l=1;if(t>0){for(i=0;;i++){p=!Array(i+1).join(1).match(/^1?$|^(11+?)\1+$/);if(p){if(i-2==l){if(c>=t-1){console.log(l+", "+i);break}c++}l=i}}}

用法(上面的脚本另存为ntp.js):

>for /l %x in (0, 1, 10) do node ntp.js %x
>node ntp.js 0
>node ntp.js 1
3, 5
>node ntp.js 2
5, 7
>node ntp.js 3
11, 13
>node ntp.js 4
17, 19
>node ntp.js 5
29, 31
>node ntp.js 6
41, 43
>node ntp.js 7
59, 61
>node ntp.js 8
71, 73
>node ntp.js 9
101, 103
>node ntp.js 10
107, 109

0

AWK-129

文件fsoe-pairs.awk

{n=2;N=1
for(;;){if(n in L){p=L[n];del L[n]}else{p=n
if(n-N==2)if(!--$0){print N", "n;exit}N=n}P=p+n++
while(P in L)P+=p;L[P]=p}}

运行它:

$ awk -f fsoe-pairs.awk
1
3, 5
$ awk -f fsoe-pairs.awk
2
5, 7
$ awk -f fsoe-pairs.awk
10
107, 109

(输入命令后的第一行,输出第二行)

这基于一种我自己的素数生成器算法,我将其称为“橡皮擦的浮动筛网”(直到我在其他地方找到它的描述),该算法仅存储所需的筛子部分和已经计算出的素数。


0

的Python 2(75)

c=input()
n=3
while c:n+=2;c-=all(n%i&~2for i in range(2,n-2))
print(n-2,n)

那么这是怎么回事?

首先,让我们看一下表达式all(n%i&~2for i in range(2,n-2)),该表达式检查是否(n-2,n)有一对双素数。

更简单的表达式all(n%i for i in range(2,n))只是n通过尝试irange中的每个除数2<=i<=n-1,并查看是否所有余数都不为零来检查是否为质数。该all检查正是这一点,因为Python对待0False和所有其他号码作为True

现在,观察除数的(n-2)%i==0确切时间。因此,我们可以执行素性检查,并通过检查两个余数在同一时间和。可以这样做。我们只能尽量除数范围为着想,但这足够了,以及因为和不能,除非除数。我们将仅尝试从奇数开始,以避免这种复杂的除数。n%i==2i>2nn-202all(n%i not in [0,2] for i in range(2,n-2))2<=i<=n-3n-2nn-1n-2n<=4n5i=2

我们将表达式n%i not in [0,2]打入n%i&~2,记住0是False,其他数字是True。运算符优先级(n%i)&(~2)正是需要的。位补码~2...11111101,因此按位and加一个数字将其2二进制位置值清零。这仅为和提供了0False)我们想要的。02

!现在我们有了该表达式,可以all(n%i&~2for i in range(2,n-2))检查n双素素对的高位数。剩下的就是遍历它们,直到我们看到它们为止c,其中c输入的数字在哪里。我们从开始5算起,2以避免除数问题。c每次遇到n有效时,我们都会递减,当时停止c=0。最后,我们打印出最后的孪生素数对。


0

T-SQL(2012 +),255个字符

一个更紧凑的T-SQL twin prime finder,也可以提高一点速度。

with t(n)as(select 2+number from spt_values where type='p')select*from(select concat(b,', ',a),rank()over(order by a)from(select n,lag(n)over(order by n)from t where not exists(select*from t f where f.n<t.n and t.n%f.n=0))z(a,b)where a=b+2)r(s,k)where k=2

可读格式:

    with t(n)as(
        select 2+number 
        from spt_values 
        where type='p'
    )
    select *
    from(
        select concat(b,', ',a),rank() over (order by a)
        from(
            select n, lag(n) over(order by n)


    from t 
        where not exists(
            select 1 from t f 
            where f.n<t.n and t.n%f.n=0)
    ) z(a,b)
    where a=b+2
) r(s,k)
where k=2

基本要点是,我们使用内置的数字表(master..spt_values type ='p')和别名(以CTE缩写)。我们添加2以消除为集合抽取0或1个平凡错误的担心,因此现在有2,2050的候选。

Z的最内层查询通过滤除任何可被小于n的整数除的数n来获得2到2050的所有质数。然后,我们使用一个漂亮的T-SQL 2012窗口函数lag,该函数使我们能够提取先前的结果,因此现在Z的结果a和b分别是质数P[n]P[n-1]。R查询创建输出字符串,过滤掉非双素数,并为我们称为K的输出创建序列号。最后,最后一个查询R允许我们通过更改其变量来过滤并获得第K个双素数。


0

Mathematica-71个字节

n=Input[];
i=j=0;
While[j<n,i++;If[And@@PrimeQ[x={i,i+2}],j++]];Print@x
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.