Encuentra el enésimo par de primos gemelos


26

Dos números primos se definen como primos gemelos si difieren en dos. Por ejemplo, 3 y 5 son primos gemelos al igual que 29 y 31.

Escriba un programa que encuentre el enésimo par de primos gemelos (donde n proviene de STDIN) y los imprima en STDOUT, separados por una coma y un espacio. Este es el código de golf, por lo que gana el código más corto.

Entrada de muestra:

3

Salida de muestra:

11, 13

55
Espera ... para que el usuario ingrese el enésimo par de primos gemelos, ¿y quieres que lo enviemos? Entonces, ¿solo repite lo que ingresa el usuario? ;-)
Iszi

Hmm ... ¡Esa redacción fue un poco incómoda! : P
Jwosty

Respuestas:


11

Haskell 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

Fuerza bruta todos los primos gemelos e imprime el enésimo par.


55
¡Buena esa! Al separar la función de filtrado y usar en interactlugar de putStrLnusted, puede ir aún más lejos y reducir esto a 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

10

CJam, 29 26 bytes

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

Pruébalo en línea.

Ejemplos

$ 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

Cómo funciona

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 caracteres, construidos sobre el comentario de aschepler

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

101 caracteres, respuesta anterior

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

Uso:

$ perl ./twin_primes.pl 10
107, 109

Explicación

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

El funcionamiento de la expresión regular de no primalidad se explica en esta pregunta SO .


..¿Que es esto?
seequ

@TheRare: Utiliza una expresión regular para verificar la prima de un número.
Zaid

1
Simplemente me voló la cabeza. Tener un +1.
seequ

@TheRare: agregué una explicación de por qué esto funciona. Estoy seguro de que todavía hay margen de mejora :)
Zaid

2
Más o menos lo que hubiera hecho. Tener algunos caracteres afeitados:$n=pop;$r='^1$|^(11+?)\1+$';($t=1x$s)=~$r||"11$t"=~$r||--$n||exit say("$s, ",$s+2)while++$s
aschepler

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

Ejecución de muestra:

$ 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

Gracias por la ayuda de Dennis, Bebe y Alchymist.


Puede guardar algunos bytes utilizando en scanflugar de argumentos de línea de comandos. Además, o=0es innecesario, ya que oes global.
Dennis

mainpodría contener una variable int predeterminada, incrementar cy ientre asignaciones y declaraciones podría acortar el código, la asignación de lpodría volver al primer bloque del tercer bloque del bucle, por lo que no necesitaría llaves y usar solo un carácter de separador en printf definitivamente podría Hazlo más compacto.
Bebe

Gracias bebe! Me di cuenta de que también tenía c<=i-1, lo cual es una tontería.
millinon

No veo una forma de afeitar un byte incrementando ila lexpresión de asignación, ya que el (nuevo) valor de ise usa para disminuir n. ¿Algun consejo?
millinon

si recuerdo bien hay un lugar donde se puede incrementar yo, pero creerlo es dependiente del compilador :(
bebe

6

CJam - 26

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

Funciona para primos menores de 10000; puede reemplazar 4con un exponente más alto para números más grandes (potencialmente hasta 10 20 ), pero el programa se volverá más lento y usará más memoria.

Pruébalo en http://cjam.aditsu.net/

Explicación:

1e4,crea la matriz [0 1 2 ... 9999]
{mp},selecciona sólo los números primos
_2f-copias de la matriz y resta 2 de cada elemento
&se cruza las dos matrices, encontrando así los números primos inferiores de cada gemelo par prime
qilee la entrada y la convierte a número entero
(=ajusta la indexa y obtiene el primo gemelo correspondiente (inferior) de la matriz
_2+copia el primo y agrega 2
", "\pone la coma y el espacio entre los dos primos


4

Mathematica - 63 caracteres

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

Notas

De hecho, esta es una implementación bastante sencilla. El acortamiento resultó en casi ninguna ofuscación.

NextPrime es una construcción que encuentra el siguiente primo después de un número.

NestWhile[NextPrime,#,#2-#1!=2&,2]& es una función anónima que encuentra el primo más grande del siguiente par de primos gemelos después de un número.

Nestaplica esta función anónima nveces.

Print[#-2,", ",#]&es una función anónima que imprime en stdout de acuerdo con las especificaciones. Lamentablemente, esto solo ocupa 18 caracteres de la solución de 63 caracteres.

Ejemplo

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

Actualización: se pueden guardar dos caracteres reimplementando esta solución CJam . Sin embargo, este algoritmo limita el valor máximo de n. Simplemente reemplace la Nest...parte porIntersection[#,#-2][[5]]&@Prime@Range[999]


¿Dónde está tu STDIN? :)
mfvonh

4

Javascript (E6) 92 96

Más corto y compatible: use el spidermonkey shell para leer stdin / escribir stdout (con coma y espacio). Encuentra el par 10000º 1260989, 1260991 en menos de un minuto en mi PC.
Podría ser más corto usando en p[n]=o=nlugar de p.push(o=n), por lo que la matriz p es escasa. Pero eso es bastante más lento, y de todos modos no voy a ganar por la longitud del código.

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)

Para probar en la consola de 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)

Sin golf

Una función que encontró todos los primeros m gemelos (devuelve el valor más grande):

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
}

Ejemplo: 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]

Solo el último:

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
}

Luego, toma esas 2 líneas y agrega 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 bytes

Decidí ir con un enfoque simple. La función tencuentra el próximo primo gemelo dado un número primo como entrada (ahora esto está incluido en la ffunción). La función fencuentra el enésimo gemelo primo. Este también es el primer programa real que escribí en J.

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

Ejemplos:

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

Solo para algunas cejas, tenga la versión sin golf.

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

Explicación:

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

Esto necesita un poco más de trabajo para cumplir con las especificaciones: "los imprime en STDOUT, separados por una coma y un espacio". Por supuesto, eso es irrelevante para el algoritmo, pero aumenta la duración del programa.
Szabolcs

@Szabolcs mejor?
seequ

Claro, +1. J es genial.
Szabolcs

@Szabolcs Realmente lo es. Aunque realmente me dobla la cabeza. Aunque cada vez es más fácil (este fue el primer programa que escribí a mano) Además gracias.
seequ

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 pero necesita agregar un espacio después de la coma cuando imprime los números
Cristian Lupascu

1
puede guardar dos caracteres más: .Count(x=>j%x==0)==2)->.Count(x=>j%x<1)<3)
Cristian Lupascu

2
Además, su clase podría llamarse en Plugar de Programy el parámetro en alugar de args.
Cristian Lupascu

1
No se compilará tal como está: tiene un extra )después del .Count(...)<3. También puede ahorrar un poco cambiando var i=int.Parse(args[0]);int f=0,c=0;a int i=int.Parse(args[0]),f=0,c=0;. Puede guardar algo más extrayendo el inicializador del bucle, entonces c=0;for(int j=1;=> c=0,j=1;for(;.
Bob

Además, una reescritura completa del cuerpo del forbucle, además de usar un nombre completo en lugar de using System: using 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 caracteres.
Bob


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"

Sin golf:

$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

Bruto obliga a un CTE a encontrar números primos, la función de ventana para contar n, seguido de una unión para encontrar el gemelo. Funciona en un segundo para salidas <1,000, poco menos de un minuto para salidas <10,000.

Golfed (SQLFiddle aquí ):

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)

Legible:

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

GolfScript 46

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

Prueba en línea: enlace

Código anotado:

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

No una más pequeña, pero una prueba de 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

Sigue obteniendo los siguientes números primos y almacena términos pares e impares, luego verifica si la diferencia es dos.

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
Por favor, no la raíz cuadrada! for (int i=2;i*i<=k;i++)
edc65

1

R, 91 caracteres

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=", ")

Nada realmente elegante:

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=", ")

Uso:

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

Lee desde stdin, sale a stdout, sale "temprano" para la entrada <= 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}}}

Uso (script anterior guardado como 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

El archivo 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}}

Ejecutándolo:

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

(1ra línea después de ingresar el comando, la 2da sale)

Esto se basa en un algoritmo generador propio principal que llamo "tamiz flotante de erastóstenes" (hasta que lo encuentre descrito en otra parte) que solo almacena la parte necesaria del tamiz y los primos ya calculados.


0

Pitón 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)

Entonces, ¿qué está pasando aquí?

Primero, veamos la expresión all(n%i&~2for i in range(2,n-2)), que verifica si (n-2,n)hay un par de primos gemelos.

La expresión más simple all(n%i for i in range(2,n))simplemente comprueba si nes primo probando cada divisor ien el rango 2<=i<=n-1y viendo si todos los restos son distintos de cero. Esto allverifica exactamente esto, ya que Python trata 0como Falsey todos los demás números como True.

Ahora, observe eso (n-2)%i==0exactamente cuando n%i==2para divisores i>2. Por lo tanto, podemos realizar la verificación de primalidad ny n-2al mismo tiempo verificando los restos para ambos 0y 2. Esto podría hacerse como all(n%i not in [0,2] for i in range(2,n-2)). Solo intentamos divisores en el rango 2<=i<=n-3por el bien de n-2, pero esto también es suficiente ndesde entonces n-1y n-2no puede ser divisores a menos que n<=4. Solo trataremos de ncomenzar de manera extraña 5para evitar esta complicación y la del divisor i=2.

Desarrollamos la expresión n%i not in [0,2]en n%i&~2, recordando que 0es Falso y otros números son True. La precedencia del operador (n%i)&(~2)es exactamente lo que se necesita. El complemento de bits ~2es ...11111101, por lo que es bit anda bit con un número que pone a cero el 2valor posicional binario. Esto da 0(es decir, False) solo para 0y 2, exactamente lo que queremos.

¡Uf! Ahora tenemos que la expresión all(n%i&~2for i in range(2,n-2))verifica si nes el número superior de un par primo gemelo. Lo que queda es iterar sobre ellos hasta que los veamos c, donde cestá el número ingresado. Comenzamos con 5y contando 2para evitar problemas de divisores. Disminuimos ccada vez que nos encontramos con algo nque funciona, deteniéndonos cuando c=0. Finalmente, imprimimos el primer par gemelo que terminamos.


0

T-SQL (2012 +), 255 caracteres

Un buscador de primos gemelos T-SQL más compacto que también se acelera un poco.

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

Formato legible por humanos ::

    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

La esencia básica es que usamos la tabla de números incorporada (master..spt_values ​​type = 'p') y alias que con un CTE como algo corto. Agregamos 2 para eliminar la preocupación de extraer 0 o 1 errores triviales para nuestro conjunto, por lo que ahora tenemos candidatos de 2,2050.

Z, la consulta más interna obtiene todos los números primos del 2 al 2050, al filtrar cualquier número n que sea divisible por un número menor que n. Luego usamos una ingeniosa función de ventanas T-SQL 2012 lagque nos permite extraer el resultado anterior, por lo que ahora los resultados de Z ayb son los primos P[n]y P[n-1]respectivamente. La consulta R crea la cadena de salida y filtra primos no gemelos y también crea un número de secuencia para la salida que llamamos K. Finalmente, la última consulta R nos permite filtrar y obtener el primo gemelo Kth cambiando su variable.


0

Mathematica - 71 bytes

n=Input[];
i=j=0;
While[j<n,i++;If[And@@PrimeQ[x={i,i+2}],j++]];Print@x
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.