Знайдіть N-ту пару близнюків


26

Два простих числа визначаються як близнюки-праймери, якщо вони різняться на два. Наприклад, 3 і 5 - близнюки-близнюки, як і 29, 31.

Напишіть програму, яка знаходить n-ту пару близнюків (де n походить від STDIN) і друкує їх на STDOUT, розділених комою та пробілом. Це код-гольф, тому виграє найкоротший код.

Зразок введення:

3

Вибірка зразка:

11, 13

5
Зачекайте ... тож користувач введе n-ту пару близнюків, а ви хочете, щоб ми вивели його? Отже, просто повторюйте те, що вводить користувач? ;-)
Ізі

Гм ... Таке формулювання було трохи незручним! : P
Jwosty

Відповіді:


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

Звертайте всі близнюки і друкуйте п- ю пару.


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

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

Перл, 101 87

87 символів, спираючись на коментар асчеплера

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

Дія регексу не первинності пояснюється в цьому питанні ЗО .


..що це?
seequ

@TheRare: Він використовує регулярний вираз, щоб перевірити престижність числа.
Заїд

1
Ви просто підірвали мені розум. Майте +1.
seequ

@TheRare: я додав пояснення, чому це працює. Я впевнений, що ще є можливість для вдосконалення :)
Zaid

2
Досить багато, що я зробив би. Майте кілька поголених персонажів:$n=pop;$r='^1$|^(11+?)\1+$';($t=1x$s)=~$r||"11$t"=~$r||--$n||exit say("$s, ",$s+2)while++$s
aschepler

8

С: 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може бути повернене до першого для третього блоку циклу, так що вам не знадобляться дужки і використовувати лише один символ роздільника в printf зробити його більш компактним.
bebe

Спасибі, бебі! Я помітив, що я теж мав c<=i-1, що просто нерозумно.
мільйон

Я не бачу способу голити байт шляхом збільшення iв lвиразі присвоєння, оскільки (нове) значення iвикористовується для декременту n. Якісь поради?
мільйон

якщо я правильно пам'ятаю, є одне місце, де можна збільшити i, але я вважаю, що його компілятор залежить :(
bebe

6

CJam - 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 відповідно до специфікацій. На жаль, це одне займає 18 символів рішення з 63 символами.

Приклад

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

4

Javascript (E6) 92 96

Коротше та сумісніше - використовуйте оболонку spidermonkey для читання stdin / write stdout (із комою та пробілом). Він знаходить, що 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
}

Потім візьміть ці 2 рядки і додайте 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-й простий близнюк. Це також буває першою фактичною програмою, яку я написав у Дж.

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 краще?
seequ

Звичайно, +1. J досить крутий.
Szabolcs

@Szabolcs Це дійсно так. Хоча це reeeeeally згинає мою думку. Хоча все легше стає (це була перша програма, яку я написав від руки). Також дякую.
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, але вам потрібно додати пробіл після коми після надрукування номерів
Крістіан Лупаску

1
ви можете зберегти ще два знаки: .Count(x=>j%x==0)==2)->.Count(x=>j%x<1)<3)
Крістіан Лупаску

2
також ваш клас може бути названий Pзамість, Programа параметр aзамість args.
Крістіан Лупаску

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 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 символів.
Боб


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, а потім об'єднання, щоб знайти близнюка. Працює за секунду для виходів <1000, трохи менше хвилини для виходів <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

GolfScript 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

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, виходить "рано" для введення <= 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

(1-й рядок після введення команди, другий - вихідний)

Це засновано на власному алгоритмі основного генератора, який я називаю "плаваючим ситом ерастостенів" (поки я не знайду його описаним в інших місцях), який зберігає лише необхідну частину сита і вже розраховані праймери.


0

Пітон 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є простим, спробувавши кожен дільник iу діапазоні 2<=i<=n-1та побачивши, чи всі залишки ненульові. Це allперевіряє саме це, оскільки Python трактує 0як Falseі всі інші числа як True.

А тепер спостерігайте за тим (n-2)%i==0, коли саме n%i==2для дільників i>2. Отже, ми можемо виконати перевірку первинності nі n-2одночасно перевірити залишки як для, так 0і для 2. Це можна зробити як all(n%i not in [0,2] for i in range(2,n-2)). Ми намагаємося лише подільників в межах 2<=i<=n-3заради n-2, але цього достатньо для , nяк добре , так n-1і n-2не можуть бути дільниками , якщо тільки n<=4. Ми спробуємо лише непарне, nпочинаючи з того, 5щоб уникнути цього ускладнення та поділу i=2.

Ми гольфи вираження n%i not in [0,2]в n%i&~2, пам'ятаючи , що 0помилкові і інші цифри True. Пріоритет оператора (n%i)&(~2)- саме те, що потрібно. Бітове доповнення ~2є ...11111101, тому його побітове andчисло з нулями виводить значення 2бінарного місця. Це дає 0(тобто False) тільки для 0і 2, саме те , що ми хочемо.

Фу! Тепер ми маємо, що вираз 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, який також трохи скорочується.

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 внутрішній самий запит отримує всі прайми з 2 по 2050 рік, фільтруючи будь-яке число n, яке ділиться на число, менше від n. Потім ми використовуємо чудову функцію вікон T-SQL 2012, lagяка дозволяє нам витягнути попередній результат, тому тепер Z-результати a і b є простими рівнями P[n]і P[n-1]відповідно. Запит R створює вихідний рядок і відфільтровує не-близнюки, а також створює порядковий номер для виводу, який ми називаємо K. Нарешті останній запит R дозволяє нам фільтрувати та отримувати Kth близнюк, змінюючи його змінну.


0

Mathematica - 71 байт

n=Input[];
i=j=0;
While[j<n,i++;If[And@@PrimeQ[x={i,i+2}],j++]];Print@x
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.