Знаходження не зовсім простих чисел


17

Якщо ви вирішили прийняти це ваше завдання, полягає в тому, щоб кодувати гольф функцією, яка повертає істинне або хибне (або якесь подібне змістовне подання так і ні), якщо число відповідає таким критеріям:

  1. Саме ціле число - це просте число АБО
  2. Будь-яке з сусідніх цілих чисел є простим

Наприклад:
Вхід 7поверне значення True.
Вхід 8також поверне значення True.
Вхід 15поверне помилковий. (Ні 14, 15, ні 16 не є простими)

Вхід повинен бути в змозі правильно повернути числа між 2 ^ 0 і 2 ^ 20 включно, тому не потрібно турбуватися про проблеми знаків або цілі переповнення.


32-бітове число переповнює, а не переповнення буфера, я думаю.
користувач невідомий

Уопс, означав "ціле переповнення". Мозок пішов на автопілоті.
Містер Лама

Відповіді:


11

J, 17

*/<:$&q:(<:,],>:)

Повертає булеві коди, закодовані як коди повернення процесу: нуль для істинного, ненульовий - для помилкового. Використання зразка:

   */<:$&q:(<:,],>:) 7
0
   */<:$&q:(<:,],>:) 8
0
   */<:$&q:(<:,],>:) 15
3

*/0 p:<:,],>:коротше і правильна (лямбда) функція([:*/0 p:<:,],>:)
випадкова


6

Пітон 85 80

def f(n):g=lambda n:all(n%i!=0for i in range(2,n));return g(n)or g(n-1)or g(n+1)

Перший раз на Code Golf, тому, мабуть, якихось хитрощів мені не вистачає.


Ви можете видалити []. всі будуть більш ніж раді працювати з генераторним виразом. Якщо ви не заперечуєте, щоб ваш код був некрасивим, ви також можете видалити пробіли між, 0і forі )та or.
странак

@stranac Awesome Велике спасибі.
Кріс Харпер

3
Внесло кілька прямих змін, сподіваємось, це все ще працює:f=lambda n:any(all(m%i for i in range(2,m))for m in[n,n-1,n+1])
Набб

@Nabb Дуже приємно. Молодці.
Кріс Харпер

5

Не справжній претендент на короткість коду будь-якими способами, але все-таки подаючи, оскільки визначення першості за регулярним вираженням закручується багатьма способами!

Python (2.x), 85 символів

import re
f=lambda n:any(not re.match(r"^1?$|^(11+?)\1+$","1"*x)for x in[n,n-1,n+1])

Ви можете вийняти цикл for і вбудувати його в регулярне вираження, перевіривши "1" * (n + 1), але починаючи з ^ 1? 1? замість цього.
Говард

4

Ruby (55 або 50 лямбда)

def f q;(q-1..q+1).any?{|n|(2..n-1).all?{|d|n%d>0}};end

або як лямбда (використовуйте g[23]для виклику)

g=->q{(q-1..q+1).any?{|n|(2..n-1).all?{|d|n%d>0}}}

Coffeescript (53)

p=(q)->[q-1..q+1].some (n)->[2..n-1].every (d)->n%d>0

<pedantic> Це повинно бути "proc", а не "лямбда" </pedantic> ;-)
Doorknob

3

Нудне рішення Mathematica, 35 !

PrimeQ[n-1]||PrimeQ[n]||PrimeQ[n+1]

15
Принаймні, ви можете пограти в нього Or@@PrimeQ/@{n-1,n,n+1}.
Говард

Це не функція.
Мартін Ендер

@ MartinBüttner: Я не знаю Mathematica, вибачте.
Ри-

2
Використовуючи версію Говарда, Or@@PrimeQ@{#-1,#,#+1}&(коса риса в його коді не потрібна)
Мартін Ендер

3

C, 112 82 72 символи

Після коментаря Ілмарі Каронен, врятувавши 30 символів, видаливши main, тепер Pповертає значення true / false. Також замінили цикл на рекурсію та ще кілька налаштувань.

p(n,q){return++q==n||n%q&&p(n,q);}P(n){return p(-~n,1)|p(n,1)|p(~-n,1);}

Оригінальна версія:

p(n,q,r){for(r=0,q=2;q<n;)r|=!(n%q++);return!r;}
main(int n,int**m){putchar(48|p(n=atoi(*++m))|p(n-1)|p(n+1));}

Ви можете зберегти 2 символи за допомогою main(n,m)int**m;.
Ільмарі Каронен

... і крім того, у виклику написано " функція коду-гольфу ".
Ільмарі Каронен

3

Математика, 24 байти

Не знаю, чому ця стара публікація з’явилася у моєму списку сьогодні, але я зрозумів, що тут математика є конкурентоспроможною.

Or@@PrimeQ/@{#-1,#,#+1}&

Безіменна функція, яка бере цілий аргумент і повертається True або False. Пряма реалізація.


PrimeQнитки над списками, так що Or@@PrimeQ@{#-1,#,#+1}&(або Or@@PrimeQ[#+{-1,0,1}]&) також працює, для -1 байта. (Хоча, мабуть, я не знаю, чи PrimeQперетягували списки у 2012 році.)
Міша Лавров


2

JavaScript (71 73 80 )

n=prompt(r=0);for(j=n-2;p=j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;alert(r)

Демонстрація: http://jsfiddle.net/ydsxJ/3/

Редагувати 1: Змінити for(i=2;i<j;i++)на for(i=1;++i<j;)(спасибі @minitech). Перетворити ifзаяву в тернар. Переміщаються r|=pі p=1в зовнішню forдля усунення внутрішніх брекетів. Збережено 7 символів.

Змінити 2: Об'єднати p=1і j++<=nдо p=j++<=n, зберегти 2 символів (спасибі @ugoren).


Ви можете використовувати for(i=1;++i<j;)замість того, for(i=2;i<j;i++)щоб зберегти ще 1 символ.
Ри-

1
@minitech: !j%iне працюватиме через перевагу. Працююча альтернатива є j%i<1.
Nabb

@Nabb: Нічого собі, ти маєш рацію. Це нерозумно.
Ри-

Як щодо p=j++<=n? Якщо тут JavaScript схожий на C, він повинен працювати.
ugoren

@ugoren: Схоже, це спрацювало, дякую!
mellamokb

2

Regex (ECMAScript), 20 байт

^x?x?(?!(x+)(x\1)+$)

Спробуйте в Інтернеті!

Наведена вище версія не обробляє нуль, але вона займає лише 1 додатковий байт:

^x?x?(?!(x+)(x\1)+$)x

Окрім додаткового бонусу, ось версія, яка дає зворотній матч 1на один менший за прем'єр, 2за прем'єр та 3на ще один за прем'єр:

^x?x??(?!(x+)(x\1)+$)x

Спробуйте в Інтернеті!


Діапазон, про який йдеться в цьому питанні, "між 2 ^ 0 і 2 ^ 20", так що 1..2 ^ 20, тому 0 немає ...
RosLuP

@RosLuP Саме тому моя основна відповідь - 20 байт і не обробляє 0 правильно. Я знаходжу цінність у тому, щоб вийти за межі точних специфікацій питання та дати більш надійні відповіді, а також відповідь, що мінімально відповідає специфікації питання.
Deadcode

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

1
@RosLuP Але в чому шкода, якщо я даю мінімальну відповідь як основну відповідь? І чи можете ви навести якісь приклади людей, які насправді так думають? Я міг би зрозуміти це, якби я дав свою єдину відповідь як надійну, але я цього не роблю.
Deadcode

1

C #, 96

Він повертає -1,0,1 за істину, все інше неправдиво.

Будь-які пропозиції зробити його коротшим було б чудово!

int p(int q){var r=q-1;for(var i=2;i<r&r<q+2;i++){if(i==r-1)break;if(r%i==0)r+=i=1;}return r-q;}

Розгорнута форма:

int p(int q){
    var r=q-1;
    for(var i=2;i<r&r<q+2;i++){
        if(i==r-1)break;
        if(r%i==0)r+=i=1;
    }
    return r-q;     
}

Я не зовсім впевнений, але я думаю, ви можете зняти if(i==r-1)break;та змінити середину forпетлі з i<rна i<r-1. Це зведе вас до 82.
Ciaran_McCarthy

1

GolfScript: 26

)0\{.:i,{i\%!},,2=@|\(}3*;

Пояснення: Найпотаємніший блок {.:i,{i\%!},,2=@|\(} визначає, чи є верхня частина стека простим, перевіряючи, чи є рівно на 2 коефіцієнти менше, ніж вершина стека. Потім він роз'єднує це з другим пунктом на стеку, який містить стан того, чи не було бачено праймеру. Нарешті, він зменшує число у верхній частині стека.

Почніть з посилення введення, ініціалізуючи попередньо бачений стан і повторіть блок 3 рази. Оскільки це буде декремент двічі, але ми почали з збільшення, це охопить n+1і n-1.


1

C #, 87 97 символів

bool p(int q){return new[]{q-1,q,q+1}.Any(x=>Enumerable.Range(2,Math.Abs(x-2)).All(y=>x%y!=0));}

Я не думаю, що це працює з 1 або 2 як вхід
Бен Райх

@BenReich Це не сталося. Мені довелося додати десять символів, щоб виправити це :(
Стів Клентон

1

CJam, 12 байт

CJam набагато молодший за цей виклик, тому ця відповідь не підходить для зеленої галочки (яку все одно слід оновити до відповіді випадкових осіб). Однак гольф це насправді було досить весело - я починав з 17 байт, а потім тричі змінив свій підхід, заощаджуючи один чи два байти кожен раз.

{(3,f+:mp:|}

Це блок, найближчий еквівалент функції в CJam, який очікує введення в стек і залишає 1 (truthy) або 0 (Falsy) на стеку.

Тестуйте це тут.

Ось як це працює:

(3,f+:mp:|
(          "Decrement the input N.";
 3,        "Push an array [0 1 2].";
   f+      "Add each of those to N-1, to get [N-1 N N+1].";
     :mp   "Test each each element for primality, yielding 0 or 1.";
        :| "Fold bitwise OR onto the list, which gives 1 if any of them was 1.";

1

F #, 68 байт (не конкуруючий)

let p n=Seq.forall(fun x->n%x>0){2..n-1}
let m n=p(n-1)||p n||p(n+1)

Спробуйте в Інтернеті!

Ось чому я люблю код гольф. Я все ще дуже зелений з F #, але я так багато дізнаюсь про те, як працює мова і що вона може зробити для таких проблем.


Чому він не конкурує?
Ніт

1
Тому що я не впевнений, чи використовую я що-небудь у F # сьогодні, чого не було, коли питання було задано у 2012 році. Я визнаю, що це педантично - навіть параноїчно. Але я пишу фармацевтичне програмне забезпечення на життя. Параноїя здорова. ;)
Ciaran_McCarthy

1
Подивіться таблицю версій F # у Вікіпедії . Залежно від потрібної вам версії, вона може бути старшою, ніж питання.



1

Java 8, 83 байти

n->n==1|p(n-1)+p(n)+p(n+1)>0int p(int n){for(int i=2;i<n;n=n%i++<1?0:n);return--n;}

Повертається true/ falseяк значення truthy / falsey.

Спробуйте в Інтернеті.

Пояснення: "

n->                    // Method with integer parameter and boolean return-type
  n==1                 //  Return whether the input is 1 (edge-case)
  |p(n-1)+p(n)+p(n+1)>0//  Or if the sum of `n-1`, `n`, and `n+1` in method `p(n)` is not 0

int p(int n){          // Separated method with integer as both parameter and return-type
  for(int i=2;i<n;     //  Loop `i` in the range [2, `n`)
    n=n%i++<1?         //   If `n` is divisible by `i`
       0               //    Change `n` to 0
      :                //   Else:
       n);             //    Leave `n` as is
                       //  (After the loop `n` is either 0, 1, or unchanged,
                       //   if it's unchanged it's a prime, otherwise not)
  return--n;}          //  Return `n` minus 1

Таким чином, int p(int n)це призведе -1до " n=0не" і "не", і призведе n-1до " n=1чи". Оскільки p(0)+p(1)+p(2)стане -1+0+1 = 0і повернеться помилковим (хоча 2це і є основним), n=1це крайній випадок, що використовує цей підхід.


Один цикл без відокремленого методу складе 85 байт :

n->{int f=0,j=2,i,t;for(;j-->-1;f=t>1?1:f)for(t=n+j,i=2;i<t;t=t%i++<1?0:t);return f;}

Повертається 1/ 0як значення truthy / falsey.

Спробуйте в Інтернеті.

Пояснення:

n->{              // Method with integer as both parameter and return-type
  int f=0,        //  Result-integer, starting at 0 (false)
      j=2,i,      //  Index integers
      t;          //  Temp integer
  for(;j-->-1;    //  Loop `j` downwards in range (2, -1]
      f=          //    After every iteration: Change `f` to:
        t>1?      //     If `t` is larger than 1 (`t` is a prime):
         1        //      Change `f` to 1 (true)
        :         //     Else:
         f)       //      Leave `f` the same
    for(t=n+j,    //   Set `t` to `n+j`
        i=2;i<t;  //   Inner loop `i` in the range [2, t)
      t=t%i++<1?  //    If `t` is divisible by `i`:
         0        //     Change `t` to 0
        :         //    Else:
         t);      //     Leave `t` the same
                  //   (If `t` is still the same after this inner loop, it's a prime;
                  //   if it's 0 or 1 instead, it's not a prime)
  return f;}      //  Return the result-integer (either 1/0 for true/false respectively)


0

R, 68 символів

f=function(n){library(gmp);i=isprime;ifelse(i(n-1)|i(n)|i(n+1),1,0)}

Використання (1 для TRUE, 0 для FALSE):

f(7)
[1] 1
f(8)
[1] 1
f(15)
[1] 0

1
Я насправді не знаю, як працює R, але ви могли просто зробити це i(n-1)|i(n)|i(n+1)замість ifelse(i(n-1)|i(n)|i(n+1),1,0)?
Ри-

Ви праві: g = function (n) {library (gmp); i = isprime; i (n-1) | i (n) | i (n + 1)} - до 56 символів! ;-)
Паоло

0

C ++

k=3;cin>>i;i--;
while(k)
{l[k]=0;
  for(j=2;j<i;j++)
   if(!(i%j))
     l[k]++;
  k--;
  i++;
}
if(!l[1]|!l[2]|!l[3])
     cout<<"1";
else cout<<"0";

Ласкаво просимо до CodeGold.SE. Якщо ви подивитесь на інші відповіді, то помітите загальний формат, який використовується для відповідей на [code-golf] питання. Ви можете застосувати його і до своїх відповідей.
dmckee


0

J, 16 символів

   (_2&<@-4 p:]-2:)

   (_2&<@-4 p:]-2:) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
1 1 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1



0

C ++ 97

ugoren, здається, побив мене до розумного рішення. Тож він тричі підходив до циклу:

P(int k){int j=1;for(int i=2;i<k;){j=k%i++&&j;}return j;}
a(int b){return P(b)|P(b+1)|P(b-1);}

0

Четвертий (gforth) , 104 байти

: p dup 1 > if 1 over 2 ?do over i mod 0> * loop else 0 then nip ;
: f dup 1- p over 1+ p rot p + + 0< ;

Спробуйте в Інтернеті!

Пояснення

Простий чек (p)

dup 1 > if          \ if number to check if greater than 1
   1 over 2 ?do     \ place a 1 on the stack to act as a boolean and loop from 2 to n
      over i  mod   \ take the modulo of n and i
      0> *          \ check if greater than 0 (not a divisor) and multiply result by boolean
   loop             \ end the loop, result will be -1 if no divisor was found (prime)
else                \ if n is less than 2
   0                \ put 0 on the stack (not prime)
then                \ end the loop
nip                 \ drop n from the stack

Основна функція (f)

dup 1- p             \ get n-1 and check if prime
over 1+ p            \ get n+1 and check if prime
rot p                \ rotate stack to put n on top and check if prime
+ + 0<               \ add the three results and check if less than 0 (at least 1 was prime)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.