Пошук простих чисел без використання "простих символів"


21

Ваше завдання, якщо ви вирішите прийняти це, - написати програму / функцію, яка приймає як вхід ціле число N. Програма / функція повинна виводити / повертати список перших N простих чисел. Але ось ось у чому: вам заборонено використовувати прості символи у своєму коді. Простий символ - це символ, кодовий код якого в Unicode є простим числом. У діапазоні для друку ASCII це:

%)+/5;=CGIOSYaegkmq

Але правило також застосовується до символів, що не належать до ASCII, якщо ваш код використовує ці.

  • Дійсний вхід - це ціле число N, де 0 <N <= T , де можна вибрати T , але воно повинно бути більше або дорівнює 10000. T не повинно бути кінцевим.
  • Для недійсних входів (не цілі числа, цілі числа поза діапазоном) киньте виняток або виведіть / поверніть нічого / null.
  • Ціле число з пробілом проміжних / кінцевих пробілів як введення вважається недійсним.
  • Ціле число з +символом як знак як вхід вважається недійсним.
  • Ціле число з провідними нулями як вхідним вважається дійсним.
  • Якщо ваша мова дозволяє передавати вже проаналізоване ціле число як вхідне, вищезазначені правила розбору (крім діапазону першого) не застосовуються, оскільки int вже розібраний.
  • Вхід завжди базовий-10.
  • Використання вбудованих простих генераторів та тестерів первинності (сюди належать функції простих факторів) не дозволяється.
  • Обмеження на джерело накладається на символи Unicode, але підрахунок байт для оцінки може бути в іншому кодуванні, якщо ви хочете.
  • Вихід може містити один зворотний новий рядок, але це не потрібно.
  • Якщо ви виводите / повертаєте список простих чисел у вигляді рядка, то кожне просте число повинно бути обмежене одним або кількома нецифровими знаками (символами). Ви можете вибрати роздільник, який ви використовуєте.
  • Це виклик з кодом, виграє найкоротший код у байтах.

Стек фрагмент, щоб підтвердити свій код

Ви можете скористатися наведеним нижче фрагментом стека, щоб переконатися, що ваш код не містить простих символів:

var primes=[],max=10000;for(var i=2;i<=max;i++){primes.push(i);}for(var N=2;N<Math.sqrt(max);N++){if(primes.indexOf(N)===-1){continue;}primes=primes.filter(function (x){return x===N||x%N!==0;});}function setText(elem,text){var z=('innerText' in elem)? 'innerText' : 'textContent';elem[z]=text;}function verify(inputCode,resultSpan){var invalidChars=[];var success=true;for(var i=0;i<inputCode.length;i++){var cc = inputCode.charCodeAt(i);if (cc>max){setText(resultSpan,"Uh oh! The char code was bigger than the max. prime number calculated by the snippet.");success = false;break;}if (primes.indexOf(cc)!==-1){invalidChars.push(inputCode[i]);}}if (invalidChars.length===0&&success){setText(resultSpan, "Valid code!");}else if(success) {  var uniqueInvalidChars = invalidChars.filter(function (x, i, self){return self.indexOf(x)===i;});setText(resultSpan, "Invalid code! Invalid chars: " + uniqueInvalidChars.join(""));    }}document.getElementById("verifyBtn").onclick=function(e){e=e||window.event;e.preventDefault();var code=document.getElementById("codeTxt").value;verify(code,document.getElementById("result"));};
Enter your code snippet here:<br /><textarea id="codeTxt" rows="5" cols="70"></textarea><br /><button id="verifyBtn">Verify</button><br /><span id="result"></span>


10
Досить жорстоко, що ;трапляється заборонено ...
ɐɔıʇǝɥʇuʎs

Якщо тестери на первинність заборонені, що робити з функціями простих факторів.
Мальтісен

@Maltysen З простих функцій факторизації ви можете дуже швидко зрозуміти, чи є число простим чи ні, тому боюся, що це заборонено. Я це уточню.
ProgramFOX

Чи маємо нам право викинути деякі з цих недійсних даних? Наприклад, якщо функція string-> int нашої мови дозволяє провідне +, потрібно видавати їх вручну розчаровуючим.
Runer112

11
Я все це схвилював і приступив до розв’язання, потім зрозумів, що закриті парени заборонені. Ну, я вийшов.
Олексій А.

Відповіді:


10

CJam, 19 18 30 34 33 19 17 21 20 байт

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

{_3\#,2>__ff*:~-<N*}

Це, мабуть, один із найбільш жахливо неефективних алгоритмів, які я коли-небудь реалізував. Але я це зробив для розміру!

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

Мій алгоритм починається з підняття 3- inputої потужності, що гарантовано дасть число, що перевищує input-ю простим, якщо вхід правильний. Потім формується список цілих чисел від 2 до цього числа мінус одне, що є достатньо великим пробілом, щоб містити всі прості числа, які ми хочемо. Щоб позбутися складених чисел ... зітхнути ..., ми створюємо список кожного попарного продукту, який повинен генерувати всі складені числа від 4 до якогось тупо великого значення, достатньо великого для наших цілей. Тоді справа лише в тому, щоб видалити кожен елемент із початкового списку, що знаходиться у цьому складеному списку, обрізати його до перших inputелементів та з'єднати елементи з символом нової лінії.

Алгоритм повинен працювати для будь-якого введення. Однак, чи має у перекладача / комп’ютера достатньо пам'яті чи часу - це зовсім інше питання, оскільки вимоги до часу та простору є експоненціальними щодо введення. Тож якщо введення для інтерпретатора в Інтернеті більше, ніж приблизно 5, або 8 для автономного, то відповідь на це питання, мабуть, ні.


3
Гей, у 17 років у вас відповідь просте кількість байтів.
Корі Огберн

Для чого вам потрібен S*?
jimmy23013

@ user23013 Недійсні входи менше 1 все ще подаються через алгоритм, вони просто створюють порожній список. Але це не є законним висновком для них, тому я з'єдную елементи списку з пробілами, щоб створити порожній вихід для цих недійсних входів.
Runer112

1
Я це помітив, чи не Sголовний персонаж?
Zacharý

Це простий характер. Я знаю, що я запізнився на 2 роки, але ця відповідь має бути недійсною
Zacharý

8

Java. 474 байт

i\u006dport j\u0061v\u0061.util.*\u003bvoid b(int b\u0029{Lon\u0067 c\u003d2L,d,f[]\u003d{}\u003bfor(f\u003dArr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029for(d\u003d0L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029for(lon\u0067 h:f\u0029d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003bj\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029,Lon\u0067.cl\u0061ss\u0029\u003b}

Бере введення через аргумент функції, виводить через викинуте виняток.

Відступ:

i\u006dport j\u0061v\u0061.util.*\u003b
void b(int b\u0029{
    Lon\u0067 c\u003d2L,d,f[]\u003d{}\u003b
    for(f\u003dArr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029
        for(d\u003d0L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029
            for(lon\u0067 h:f\u0029
                d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003b
    j\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029,Lon\u0067.cl\u0061ss\u0029\u003b
}

Видалені символи:

import java.util.*;
void b(int b){
    Long c=2L,d,f[]={};
    for(f=Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
        for(d=0L;f[b]<1;f[b]=d<1?c:0,d=0L,c++)
            for(long h:f)
                d=h>0&&c/h*h==c?1:d;
    javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class);
}

Пояснення:

Long c,d,f[]={};                                                //Initialize variables.

for(f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
    f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L)            //Initialize f to an array of 0's.
                                                     b-->0      //Iterate over the first b primes.

for(d=0L;f[b]<1;f[b]=d<1?c:0,d=0L,c++)
    d=0L                        d=0L                            //Initialize d to 0.
         f[b]<1                      c++                        //Increment c while the b'th prime is 0.
                f[b]=d<1?c:0                                    //If d = 0, the b'th prime = c, else continue.

for(long h:f)                                                   //Iterate over all found primes.

d=h>0&&c/h*h==c?1:d;
  h>0                                                           //Ignore non-found primes.
       c/h*h==c                                                 //Equivalent to c%h==0
               ?1:d                                             //If h is prime and c is divisible by h, d = 1. Otherwise d stays unchanged.

javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class)   //Print solution to stderr
javax.xml.bind.JAXB.unmarshal(                   ,Long.class)   //Prints what's contained to stderr.
                                 Arrays.asList(f)               //Convert f to list.
                              ""+                               //Convert to string.

Моє оригінальне рішення використовувало returnтвердження. Задавши це питання на StackOverflow, регетман був досить люб'язним, щоб забезпечити спосіб виводу / повернення без використання простих літер.

Як завжди, пропозиції вітаються :)


3
+1. Це вам мало бути важко зрозуміти і rgettman. Дуже вражає. :)
ТНТ

5

Рубі, 74

->n,*o{o<<[2..n*n][0].find{|x|!o.find{|y|1.>x.^y.*x.div y}}until o[n-1]
o}

Пояснення:

*oініціалізує порожній вихідний масив. поки у нього немає nелементів, ми знаходимо найменше число> = 2, яке не ділить жоден предмет, який зараз знаходиться o, і додаємо його до o. Щоб перевірити на поділ, поступається. Усі хороші оператори заборонені, і я навіть не можу користуватися divmod. Найкраще, що я міг бачити, - це використання x.div y, яке приймає х, поділене на y і округлення, а потім помноження на y знову. Якщо вона дорівнює x, не було округлення, тому y ділить x. 1.>x.^- це тест рівності, перевіряючи, чи є результат xor 0. .Перш ніж кожен оператор, тому що ви не можете змішати .безпровідні виклики операторів та виклики методів, що не містять дужки.

Редагувати: специфікації для перевірки діапазону були додані після того, як я опублікував це, я думаю. Для виконання потрібно 79 символів:

->n,*o{o<<[*2..-~n*n].find{|x|!o.find{|y|1.>x.^y.*x.div y}}until o[n-1]||n<1
o}

4

CJam, 38 37 30 байт

{_~2#,2>\{(\{1$37c~},\p}*'<(~}

Спробуйте тут

Я думаю, що це повинно відповідати всім правилам і працює для будь-якого негативного N (тобто Т є нескінченним). Це жахливо неефективно, тому не намагайтеся це робити у великій кількості.

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

Більша частина коду - це перевірка введення, а потім сита Ератосфена. Мені потрібно було лише подолати обмеження введення в 3 місцях:

  • )приріст у CJam. Мені це знадобилося один раз, але я міг би замінити його ~(порозрядне доповнення), оскільки я все-таки збирав цифри після цього.
  • %є модулем. Я використовую 37c~натомість, який спочатку створює персонажа, %а потім оцінює це. Це робить код набагато повільніше.
  • ;вискакує і відкидає елемент зі стека. Мені потрібно це зробити в кінці. Натомість я використовую, '<(~який підштовхує персонажа <, зменшує його і оцінює це.

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

@ Runer112 Нам дозволяється писати "функцію, яка приймає ціле число". Не "функція, яка приймає рядкове представлення цілого числа".
Мартін Ендер

3

Bash + coreutils, 227 байт

printf -vb br`dc<<<Di14B8209P`
printf -vc -- $[$1-0]
[ "${1#$c}" -o $c -lt 1 ]||{
for i in {2..104729}
{
for f in `jot $[i-1] $[i-1] 1`
{
[ 0 -lt `dc<<<"$i $f~p"` ]||$b
}
[ $f -lt 2 ]&&printf $i\ &&: $[c--]
[ $c -lt 1 ]&&$b
}
}

Це було досить хитро. Я натрапив на деякі речі:

  • Більшість петель (while і until) є непридатними, тому що вони найбільш близькі до doneключового слова оболонки і не можуть бути результатом змінного розширення (якщо evalне використовується, але це теж поза). Єдиний придатний цикл - це for/ inщо дозволяє {/ }замість do/ done. for (( ; ; ))також не використовується.
  • =немає, тому нам потрібен інший спосіб призначити змінні. printf -vдобре для цього.
  • Ми знаємо, що p (10000) - 104729, тому для зовнішньої петлі для потенційних простих ліній ми можемо просто перевести цикл від 2 до 104729 і перервати, як тільки у нас буде достатня кількість простих
  • jotформує перелік потенційних факторів у внутрішньому циклі. Якщо потенційний фактор ділить потенційний простір, то він не є простим, і ми вириваємось рано
  • На щастя break, це вбудована оболонка, а не ключове слово, тому може генеруватися в результаті розширення. dcперетворює базове 13 число в бітестрім eak.
  • Щоб перевірити, чи потенційний коефіцієнт ділить потенційний простий, ми не можемо використати звичайні /або %арифметичні оператори оболонки. Таким чином, це передається в оператора dcs ~, який виштовхує коефіцієнт і залишок до стеку.
  • -lt - менше ніж - є єдиним оператором порівняння оболонки.
  • echoне використовується для виводу. printfпрацює, хоча ми уникаємо%

Отримати правильну перевірку вводу - це неприємно. У випадку недійсного введення нічого не повертається.

Вихід:

$ ./primenoprime.sh 10
2 3 5 7 11 13 17 19 23 29 $ 

3

Haskell, 90 байт

\n->[fst c|c<-zip[p|p<-[2..],not$or[b>p-1&&b-1<p|b<-[u*v|u<-[2..p-1],v<-[2..p-1]]]][1..n]]

Це анонімна функція, яка приймає ціле число n як вхід .

Принцип роботи: [p|p<-[2..],not$or[b>p-1&&b-1<p|b<-[u*v|u<-[2..p-1],v<-[2..p-1]]]](перший приклад простого ряду однокласників у вікі Haskell, але із elemзаміненою функцією) створює нескінченний список простих ліній. zipвона з числами від 1до , nщоб зробити список (prime, seq. number)пар. Видаліть сл. номер, знову ж. Результат - це список простих розмірів n.


1

Іржа, 64897 байт

|n|println!{"{:?}",&[2,3,6-1,7,11,13,17,19,23,29,31,37,41,43,47,60-7,0x3b,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,0x97,0x9d,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,0xfb,0x101 ...}

(код відключений через обмеження символів, повне рішення тут )

Наступні функції іржі недоступні через основне обмеження:

  • функціонує виклики, як вони вимагають ')'
  • регулярні прив'язки, оскільки вони вимагають let (e)
  • макроозначення, вони вимагають макро-правил! (a, e, m)
  • заяви про відповідність, вони вимагають відповідності (a, m) та => (=)
  • змінність, оскільки вона завжди вводиться з ключовим словом mut (m).
  • повернення (e), перерва (a, e), продовження (e)
  • else (e)

Що ви можете технічно використовувати:

  • якщо. Але без іншого вони марні в виражальних контекстах, тому корисні лише для побічних ефектів.
  • макроси Стандартні макроси, як друк! зазвичай супроводжується (), але насправді легально використовувати натомість {} або []. Без цього завдання було б неможливим.
  • закриття, у самому вузькому сенсі. Ви не можете їх зателефонувати (вимагає ()) або зв'язати їх (вимагає дозволити), але ви можете визначити один нерекурсивний. Без цього завдання, очевидно, стало б неможливим.
  • конструкцій.
  • для петель. Вони є багатообіцяючими, оскільки вони фактично дозволяють прив'язувати змінну, і вони беруть ітератор, який ще можна визначити за допомогою синтаксису діапазону. Ітератор може бути навіть виразом.
  • Вбудовані оператори, крім +,% та /. Логічні оператори короткого замикання здаються перспективними.

Я просто не міг зробити що-небудь Тьюрінга в комплекті з цими інструментами. Мені шкода. Залишилося лише включити повних 10000 праймедів, очищених від 5-х. Принаймні, ви можете нарізати його і мати правильне рішення, у самому вузькому сенсі.

Я дуже хотів би, щоб фахівці з дайвінгу на Тюрінгу (або на Іржі!) Сказали мені, чи можна було б зробити щось краще!


1

GNU APL, 75 68 67 65 59 56 55 символів

⎕IOповинно бути 1.

∇z←p n
z←2,j←3
j←j--2
→2×⍳∨⌿1>z|j
z←z,j
→2×⍳n>⍴z
z←n↑z∇

Я повернувся на цей місяць пізніше зрозумівши, що у мене є додатковий простір!


Це в кодуванні APL чи UTF-8? Якщо перетворити його в кодування APL (і воно дійсне), воно буде набагато коротшим у байтах.
NoOneIsHere

UTF-8. Так, але в цих низьких символьних точках, буде більше праймів.
Zacharý

Якщо бути точним, тепер байт рахується в APL, але обмеження на джерело є Unicode. (Я зрозумів, що виклик дозволений підрахунком байтів Unicode)
Zacharý

0

Pyth - 12 байт

Використовує функцію головної факторизації pyth, щоб побачити, чи # є простим. !tPTТрюк щодо використання, запропонований мені у моїй відповіді на праймери під мільйонною проблемою.

<f!tPTr2^T6Q

Оскільки фільтр працює лише для праймерів під n, а не першого n, я просто шукав інверсію pi (x) на 10000 і отримував 104000, тому я використовую прайми під 10 under і отримую перший n. Це на самому ділі не працювати, так що ви повинні перевірити шляхом заміни ^T6з ^T3і обмежити п до менш 1000. Введення зі стандартного вводу і виводу на стандартний висновок.

<          Q     Slice first n
f     r2^T6      filter on range 2->10⁶
 !               Logical not (gives true if tail is empty)
  t              Tail (all but first, so gives empty if prime fact is len 1)
   PT            Prime factorization of filter var (len 1 if num is prime)

5
З правил: "Використання вбудованих простих генераторів та тестерів первинності не дозволяється."
Runer112

@ Runer112 Так, але це не тестер первинності, це основний чинник, знаходиться на межі правил. Я, мабуть, повинен запитати, чи це дозволено.
Малтісен

@Maltysen "Використання вбудованих простих генераторів та тестерів первинності (сюди входять функції простих факторів) не дозволяється" - мені здається досить зрозумілим.
Цифрова травма

4
@DigitalTrauma уточнення "(це включає функції простих факторів)" було додано після розміщення цієї відповіді.
Мартін Ендер

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