Це число є простим?


195

Вірите чи ні, у нас ще не існує виклику кодового гольфу для простого тесту на первинність . Хоча це може бути не найцікавішим викликом, особливо для "звичайних" мов, воно може бути нетривіальним для багатьох мов.

Код Розетти містить списки за мовою ідіоматичних підходів до тесту на первинність: один використовує тест Міллера-Рабіна, а інший використовує пробний поділ . Однак "найідіоматичніші" часто не збігаються з "найкоротшими". Прагнучи зробити головоломки програмування та Code Golf перейти на сайт для кодового гольфу, це завдання намагається скласти каталог найкоротшого підходу з усіх мов, подібний до "Привіт, світ!" і Гольф вам королева за велике благо! .

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

Завдання

Напишіть повну програму, яка з урахуванням суворо додатного цілого числа n як вхідного сигналу визначає, чи n є простим, і надрукує відповідно значення " truthy" або "false" .

Для цієї задачі ціле число є простим, якщо воно має рівно два суворо додатних дільника. Зауважте, що це виключає 1 , який є єдиним суто позитивним дільником.

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

Вхідні дані

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

  • Якщо (і лише якщо) ваша мова не може прийняти будь-який вид введення користувача, ви можете жорстко ввести вхід у програмі.

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

    Для підрахунку балів подайте програму, яка відповідає входу 1 .

Вихідні дані

Вихідні дані повинні бути записані в STDOUT або найближчу альтернативу.

Якщо можливо, вихід повинен складатися виключно з правдивого або хибного значення (або його рядкового подання), необов'язково супроводжуючись одним новим рядком.

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

Додаткові правила

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

  • Подання на більшості мов будуть оцінюватися в байтах у відповідному попередньому кодуванні, як правило (але не обов'язково) UTF-8.

    Наприклад, мова Piet буде оцінена в коделях, що є природним вибором для цієї мови.

    Деякі мови, як-от папки , досить складно оцінити. Якщо ви сумніваєтесь, будь ласка, запитайте про Meta .

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

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

  • Якщо ваша обрана мова є тривіальним варіантом іншої (потенційно більш популярної) мови, на яку вже є відповідь (подумайте, основні або діалекти SQL, оболонки Unix або тривіальні похідні Brainfuck, як Headsecks або Unary), подумайте про додавання примітки до існуючої відповіді, що те саме або дуже схоже рішення є найкоротшим в іншій мові.

  • Вбудовані функції для перевірки простоти будуть дозволені. Цей виклик призначений для каталогізації найкоротшого можливого рішення кожною мовою, тому якщо коротше використовувати вбудовану мову, перейдіть на це.

  • Якщо вони не були відмінені раніше, застосовуються всі стандартні правила , включаючи http://meta.codegolf.stackexchange.com/q/1061 .

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

Каталог

Фрагмент стека внизу цієї публікації генерує каталог з відповідей а) як список найкоротших варіантів для кожної мови та б) як загальний таблиця лідерів.

Щоб переконатися, що ваша відповідь відображається, будь ласка, почніть свою відповідь із заголовка, використовуючи наступний шаблон Markdown:

## Language Name, N bytes

де Nрозмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:

## Ruby, <s>104</s> <s>101</s> 96 bytes

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

## Perl, 43 + 2 (-p flag) = 45 bytes

Ви також можете зробити ім'я мови посиланням, яке з’явиться у фрагменті:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


Чи можу я вважати вхідні дані як від'ємні числа, де abs (введення) було б числом, яке я тестую?
Стен Струм

Ні, вхід - це суворо додатне ціле число.
Денніс

1
@LyndonWhite Це задумано як каталог (на зразок "Привіт, світ!" ) Тестів на первинність, тому уніфікований формат подання здався кращим. Я шкодую про одне з двох рішень щодо цієї проблеми, а інше - лише тестування детермінованої первинності.
Денніс

1
@Shaggy Схоже, що це питання для мета.
Денніс

1
Так, я про це думав. Я дозволю вам зробити відзнаку, бачачи, як це ваше завдання.
Кудлатий

Відповіді:


225

Привіт Світ! , 13

hello, world!

83
Ви, як, просто створили цю мову, саме для цього подання? ;)
ETHproductions

41
@ETHproductions Схоже, остання фіксація була 10 днів тому.
Геобіт

39
Я сподівався мати мову в трохи кращій формі, перш ніж зв’язуватися з нею де завгодно, але це завдання було викладене, і я не втримався.
гістократ

31
Я майже сказав, що підвішування на вході 1 - це правильна функціональність.
iamnotmaynard

21
Найкраще в тому, що програма не просто вбудована, кожен персонаж відіграє свою роль у отриманні правильного результату.
ETHproductions

157

Шестикутник , 29 байт

.?'.).@@/'/.!.>+=(<.!)}($>(<%

Читаною версією цього коду є:

   . ? ' .
  ) . @ @ /
 ' / . ! . >
+ = ( < . ! )
 } ( $ > ( <
  % . . . .
   . . . .

Пояснення: Він перевіряє, чи є число від 2 до n-1, яке ділить n.

Ініціалізація:

Запишіть n в одну комірку пам'яті і n-1 в іншу:

   . ? ' .
  . . . . .
 . . . . . .
+ = ( . . . .
 . . . . . .
  . . . . .
   . . . .

Особливий випадок n = 1:

Роздрукуйте 0 і припиніть

   . . . .
  . . . @ .
 . . . ! . .
. . . < . . .
 . . . . . .
  . . . . .
   . . . .

Петля

Обчисліть n% a і зменшіть a. Закінчіть, якщо a = 1 або n% a = 0.

   . . . .
  ) . . . /
 ' / . . . >
. . . . . . .
 } ( $ > ( <
  % . . . .
   . . . .

Випадок a = 1:

Збільшити 0 до 1, роздрукувати його та припинити. (Вказівник інструкції працює у напрямку NE і циклічно від східного кута до південно-західного кута. І $ гарантує, що він ігнорує наступну команду)

   . . . .
  . . . @ .
 . . . ! . .
. . . < . . )
 . . $ . . <
  . . . . .
   . . . .

Запис a% n = 0:

Роздрукуйте 0 і завершіть (вказівник інструкції працює з SW та петлями вгорі до @

   . . . .
  . . @ . .
 . . . . . >
. . . . . ! .
 . . . . . .
  . . . . .
   . . . .

61
Святе лайно, ось один вражаючий перший пост. :) Я висуну нагороду прямо зараз (я присуджую її за 7 днів, щоб привернути ще трохи уваги до вашої відповіді). Ласкаво просимо до PPCG!
Мартін Ендер

35
Чудова відповідь! +1 для " зчитувальних версій цього коду: <...> " :-)
agtoever

68

Шестикутник , 218 92 58 55 байт

Примітка: Ця відповідь була жорстоко побита рішенням довжини 4 у форматі Etoplay.

)}?}.=(..]=}='.}.}~./%*..&.=&{.<......=|>(<..}!=...&@\[

Перша в історії нетривіальна (тобто нелінійна) програма шестикутників! Він заснований на тому ж квадрато-факторіальному підході, що і відповідь Sp3000 Лабіринт . Почавши з шестикутника розміром 10, мені вдалося стиснути його до розміру 5. Однак мені вдалося повторно скористатися деяким дублікатом коду, і в коді все ще є купа недоліків, тому розмір 4 може просто бути можливим.

Пояснення

Щоб зрозуміти код, спершу потрібно розгорнути його. Шестикутна вкладка будь-якого вихідного коду до наступного по центру шестикутної цифри з відсутності ops ( .), що є 61. Потім він переставляє код у звичайний шестикутник відповідного розміру:

     ) } ? } .
    = ( . . ] =
   } = ' . } . }
  ~ . / % * . . &
 . = & { . < . . .
  . . . = | > ( <
   . . } ! = . .
    . & @ \ [ .
     . . . . .

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

             . . . . . . . . . . . . .
            . . . . . . . . . . . . . .
           . . . . . . . . . . . . . . .
          . . . . . . . . . . @ . . . . .
         . . . . . . . . . . ! . . . . . .
        . . . . . . . . . . % . . . . . . .
       . . . . . . . . . . ' . . . . . . . .
      . . . . . . . . . . & . . . . . . . . .
     . . . . . . . . . . { . . . . . . . . . .
    . . . . . . . . . . * . . . . . . . . . . .
   . . . . . . . . . . = . . . . . . . . . . . .
  . . . . . . . . . . } . . . . . . . . . . . . .
 ) } ? } = & { < . . & . . . . . . . . . . . . . .
  . . . . . . . > ( < . . . . . . . . . . . . . .
   . . . . . . = . . } . . . . . . . . . . . . .
    . . . . . } . . . = . . . . . . . . . . . .
     . . . . | . . . . | . . . . . . . . . . .
      . . . . * . . . ) . . . . . . . . . . .
       . . . . = . . & . . . . . . . . . . .
        . . . . > } < . . . . . . . . . . .
         . . . . . . . . . . . . . . . . .
          . . . . . . . . . . . . . . . .
           . . . . . . . . . . . . . . .
            . . . . . . . . . . . . . .
             . . . . . . . . . . . . .

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

Перш ніж ми почнемо, слово про макет пам'яті Гексагоні. Це трохи схоже на стрічку Brainfuck на стероїдах. Насправді це не стрічка, а сама шестикутна сітка (нескінченна), де кожне ребро має ціле значення, яке спочатку дорівнює 0 (а на відміну від стандартного Brainfuck, значення підписуються цілими числами довільної точності). Для цієї програми ми будемо використовувати чотири ребра:

введіть тут опис зображення

Ми будемо обчислювати факторіал на ребро А , відраховувати наш вхід на краю З і зберегти іншу копію введення (для по модулю) на ребра D . B використовується як тимчасовий край для обчислень.

Вказівник пам’яті (МП) починається на краю А і вказує на північ (це важливо для переміщення МП навколо). Тепер ось перший біт коду:

)}?}=&{

)приріст краю від A до 1основи факторіалу. }змушує МП зайняти правий поворот, тобто перейти до краю С (вказує на північний схід). Тут ми читаємо вхід як ціле число з ?. Потім беремо ще один правий поворот до краю D с }. =перевертає MP, таким чином, що вона вказує на вершину разом з C . &копіює значення з C (вхід) у D - значення копіюється зліва, оскільки поточне значення є непозитивним (нульовим). Нарешті, ми робимо МП взяти лівий поворот назад в C з {.

Далі, <це технічно галузь, але ми знаємо, що поточне значення є позитивним, тому IP завжди буде повернути праворуч у бік >. Гілка хіт від бічних діє як дзеркало, таким чином, що IP -по горизонталі знову рухається, по напрямку до (, який зменшує значення в C .

Наступна гілка - <це насправді філія зараз. Ось так ми n-1переходимо донизу 1. Незважаючи на те, що поточне значення в С є позитивним, IP приймає поворот праворуч (для виконання циклу). Як тільки ми вдаримо до нуля, він замість цього поверне ліворуч.

Давайте подивимось на цикл «тіло». |Прості дзеркала, то >і <також використовуються в якості дзеркала знову. Це означає, що фактичне тіло циклу зводиться до

}=)&}=*}=

}переміщує МП до краю В , =повертає його напрямок до вершини ABC . )збільшує значення: це актуально лише для першої ітерації, де значення B все ще дорівнює нулю: ми хочемо переконатися, що воно є позитивним, таким чином, щоб наступна інструкція &копіювала правого сусіда, тобто A , тобто поточне значення факторіалу обчислення, в B .

}потім переміщує МП до А , =повертає його знову, щоб стикатися із загальною вершиною. *примножує обидва сусідів, тобто краю B і C і зберігає результат в . Нарешті, ми маємо ще одне повернутися до C , як і раніше стикається з вершиною ABC .}=

Я сподіваюся , що ви можете побачити , як це обчислює факторіал n-1в A .

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

&}=*{&'%!@

Оскільки C дорівнює нулю, &копіює лівий сусід, тобто факторіала в . переходить до B і зберігає твір двох копій факторіала (тобто квадрат) в B . повертається до C , але не повертає MP. Ми знаємо , що поточне значення тепер позитивне, тому введення копій з D в C . МП в зворотному напрямку вправо, тобто на . Пам'ятайте, квадрат факторіала в B , а вхід в C . Тож обчислюємо саме те, що ми шукаємо.}=*{&'%(n-1)!^2 % n!друкує результат у вигляді цілого числа (0 або 1) та @припиняє програму.


Гаразд, але це була версія без вовків. А як щодо версії для гольфу? Вам потрібно знати ще дві речі про шестикутник:

  1. Краї загортаються. Якщо IP потрапляє на край шестикутника, він переходить до протилежного краю. Це неоднозначно, коли IP потрапляє прямо на кут, тому потрапляння на кут також виконує роль гілки: якщо поточне значення є позитивним, IP переходить до краю сітки праворуч, в іншому випадку - до лівого зліва.
  2. Насправді є 6 IP-адрес. Кожен з них починається в іншому кутку, рухаючись по краю за годинниковою стрілкою. Один з них активний одночасно, а це означає, що ви можете просто проігнорувати інші 5 IP-адрес, якщо ви цього не хочете. Ви можете переключитися на наступний IP (у порядку годинникової стрілки) за допомогою ]та до попереднього за допомогою [. (Ви також можете вибрати конкретну, за допомогою якої #, але це вже інший час.)

У ньому також є кілька нових команд: \і /дзеркала, як |, і ~помножує поточне значення на -1.

Тож як нелінійна версія перекладається на гольф-версію? Лінійний код налаштування )}?}=&{та основна структура циклу можна знайти тут:

        ) } ? } .  ->
       . . . . . .
      . . . . . . .
     . . . . . . . .
->  . = & { . < . . .
     . . . . . > ( <
      . . . . . . .
       . . . . . .
        . . . . .

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

        ) . . . .
       = . . . ] .
      } = . . } . .
     ~ . / . * . . .
    . . . . . . . . .
     . . . = . > ( <
      . . } . = . .
       . & . \ [ .
        . . . . .

Після відскоку від гілки на південний схід, IP обертається навколо краю до двох =у верхньому лівому куті (які разом є неопераційними), а потім відскакує від /. ~Інвертує знак поточного значення, що важливо для подальших ітерацій. IP знову обертається навколо того ж краю і, нарешті, потрапляє [там, де контроль передається іншому IP.

Цей тепер виконується, ~}=)&}=*}який скасовує заперечення, а потім просто запускає тіло неперевершеного циклу (мінус =). Нарешті, він потрапляє, ]які руки повертаються до початкового IP-адреси. (Зверніть увагу, що наступного разу, коли ми виконаємо це IP, воно почнеться з того місця, де воно припинилося, тому спочатку потрапить у кут. Нам потрібне поточне значення має негативне значення для того, щоб IP повернувся на північно-західний край замість південного сходу.)

Як тільки оригінальний IP поновлює контроль, він відскакує \, виконує решту, =а потім натискає, >щоб перейти до наступної ітерації циклу.

Тепер справді божевільна частина: що відбувається, коли цикл припиняється?

        ) . . . .
       . ( . . ] =
      . . ' . } . }
     . . . % * . . &
    . . . . . . . . .
     . . . = | . . <
      . . } ! . . .
       . & @ . . .
        . . . . .

ІС рухається на північний схід і утворює <діагональ північного сходу. Таким чином, він закінчується на тому ж шляху виконання, що і тіло циклу ( &}=*}]). Що насправді досить круто, тому що саме такий код ми хочемо виконати в цей момент, принаймні, якщо ми додамо ще один =}(бо }=}еквівалентний {). Але як це насправді знову не входить у попередній цикл? Тому що ]змінюється на наступний IP, який зараз є (поки що не використовується) IP, який починається у верхньому правому куті, рухаючись на південний захід. Звідти IP продовжується по краю, завертається до верхнього лівого кута, рухається вниз по діагоналі, відскакує від |і закінчується @при виконанні остаточного біта лінійного коду:

=}&)('%!@

( )(Зрозуміло, що це необов'язково - я повинен був додати те, (що )вже був там.)

Фу ... який безлад ...


Приємно! Наскільки це нове? Також ви можете створити сторінку esolangs щоразу, коли отримаєте стабільний випуск
mbomb007,

18
@ mbomb007 Я реалізував мову два дні тому (і розробив її за два-три дні до цього). І так, я обов'язково додам сторінку esolangs, але я думаю, що специфікація ще не на 100% стабільна (є, наприклад, 3 команди без призначення). Як тільки я відчую, що він стабільніший, я додам його до обох езолангів і до нашого метапосту.
Мартін Ендер

Під розгорнутим шестигранником він загортається до самого лівого кута (the 1) . Про що 1ти там говориш?
mbomb007

@ mbomb007 виправлено. )Звичай бути 1.
Мартін Ендер

5
+1 лише за рівень деталізації у вашому поясненні того, як це працює. Якщо більше мов прийшло з прикладом, що детально більше людей могли їх використовувати: D
jdarling

66

Pyth, 4 байти

}QPQ

Друкує Trueабо False.


12
Я знаю, що це старе, але тепер ви також можете зробити так: P_Q і збережіть 1 байт.
drobilc

14
Тепер це можливо зP_
Blue

3
@drobilc Ви можете вирізати Q, як EOF, коли функція очікує на аргумент, вона використовує вхід
Stan Strum

55

Сітківка , 16 байт

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

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

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

Програма Retina, що складається з одного рядка, розглядає цей рядок як регулярний вираз і друкує кількість збігів, знайдених на вході, що буде 0для складених чисел і 1для простих чисел.

Lookahead гарантує, що вхід не є композиційним: зворотний трекінг намагатиметься виконати всі можливі підрядки (щонайменше з двох символів) для (..+), lookahead потім намагається співставити решту вводу, повторюючи те, що було зроблено тут. Якщо це можливо, це означає, що на вході є дільник, більший за 1, але який менший від самого себе. Якщо це так, негативний результат пошуку викликає збій. Для прайметів такої можливості немає, і поєдинок триває.

Єдине питання полягає в тому, що ця програма пошуку також приймає 1, тому ми виключаємо це, узгоджуючи принаймні два символи з ...


Це насправді неправильний вираз, оскільки праймери не утворюють звичайної мови.
PyRulez

@PyRulez Більшість ароматів регексу в реальному світі набагато потужніші, ніж теоретична концепція регулярних виразів. Хоча я покращив формулювання.
Мартін Ендер

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

52

CJam, 4 байти

qimp

CJam має вбудований оператор для перевірки первинності.


18
Як варіант:limp
Sp3000

43
pimpмій cjam.
недолік

12
pimpоб'єктивно більше сутенера
MickLH

1
Ви також можете зробитиl~mp
корови гукають

12
@Cyoce, qчитає рядок введення, iаналізує його як ціле число і mpє вбудованим. CJam має дві групи вбудованих двома шарами: починаються "розширені" і починаються e"математичні"m
Пітер Тейлор

47

HTML + CSS, 254 + n макс * 28 байт

Ми можемо перевірити первинність, використовуючи регулярні вирази. Mozilla має @document, що визначається як:

@document [ <url> | url-prefix(<string>) | domain(<string>) | regexp(<string>) ]# {
  <group-rule-body>
}

Для фільтрування елементів за допомогою CSS на основі поточної URL-адреси. Це один прохід, тому ми повинні зробити два кроки:

  1. Отримайте інформацію від користувача. Цей вхід повинен якось відображатися в поточній URL-адресі.
  2. Відповідь користувачеві якомога менше коду.

1. Отримання вводу

Найкоротшим чином я можу зрозуміти, як отримати введення та перенести це до URL-адреси - це GETформа з прапорцями. Для регулярного вираження нам просто потрібна унікальна рядок, щоб підрахувати кількість виступів.

Отже, ми почнемо з цього (61 байт):

<div id=q><p id=r>1<p id=s>0</div><form method=GET action=#q>

Ми отримали два унікальних <p>s, щоб вказати, чи є введене число простим (1) чи ні (0). Ми також визначаємо форму та її дію.

Після цього n максимум прапорців з такою ж назвою (n max * 28 байт):

<input type=checkbox name=i>

Після цього елемент подання (34 байти):

<input name=d value=d type=submit>

2. Відображення відповіді

Нам потрібен CSS (159 байт), щоб вибрати <p>для відображення (1 або 0):

#q,#s,#q:target{display:none}#q:target{display:block}@-moz-document regexp(".*\\?((i=on&)?|(((i=on&)(i=on&)+?)\\4+))d=d#q$"){#s{display:block}#r{display:none}}

»Спробуйте це на codepen.io (лише для firefox)


12
+1: Це моє улюблене зловживання HTML часом і таке, що змушує мене кохати кодегольф.
кіт

Це, безумовно, цікаво, але я не впевнений, чи відповідає він цим правилам. Зокрема, я не думаю, що він відповідає Вашому алгоритму [...] теоретично повинен працювати для довільно великих цілих чисел. Не могли б ви також використати регулярний вираз для значення поля введення?
Денніс

@Dennis Можливо. Напевно, навіть. Але це не вирішило б проблему, про яку ви згадали. Я залишаю це як неконкурентний запис, тому що це найбільш актуальна проблема для цього.
mınxomaτ

Чому ні? Якщо у полі введення є номер унарного, ваш код більше не залежатиме від максимальної кількості.
Денніс

4
Гм, я подумав про це трохи більше, і насправді немає різниці між наявністю лише x прапорців і інтерпретатором, який має лише y-бітові числа. Ігноруйте мій попередній коментар.
Денніс


40

Шестикутник , 28 байт

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

?\.">"!*+{&'=<\%(><.*.'(@>'/

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

Я використовую теорему Вілсона, як це зробив Мартін у своїй відповіді : Дано n, я виводжу(n-1!)² mod n

Ось вона розгорнула програму:

   ? \ . "
  > " ! * +
 { & ' = < \
% ( > < . * .
 ' ( @ > ' /
  . . . . .
   . . . .

І ось читабельна версія:

Дуже читабельний

Пояснення:

Програма має три основні етапи: ініціалізація , факторний та вихідний .

Модель пам'яті шестикутника - це нескінченна шестикутна сітка. Я використовую 5 місць пам'яті, як показано на цій схемі:

Пам'ять

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

Ініціалізація:

Ініціалізація

Покажчик інструкцій ( IP ) починається у верхньому лівому куті, йде на Схід. Покажчик пам'яті ( МП ) починається з IN .

По-перше, ?зчитує число з введення та зберігає його в IN . IP залишається на блакитному шляху, який відображається \. Послідовність "&(переміщає MP назад і вліво (до A ), копіює значення з IN в A і зменшує його.

Потім IP виходить з однієї сторони шестикутника і знову входить в іншу сторону (на зелену стежку). Він виконує '+який переміщує MP в B і копіює те , що було в . перенаправляє IP на Захід.<

Фактор:

Я обчислюю факторіал певним чином, так що проводити квадратик легко. Я зберігаю n-1!в B і C так.

Факторний

Покажчик інструкцій починається на синій стежці, спрямовуючи на Схід.

='змінює напрямок МП і переміщує його назад до C . Це еквівалентно, {=але мати місце, =де це було б корисно пізніше.

&{копіює значення з до C , потім переміщує MP назад в . Тоді IP йде слідом за зеленою стежкою, нічого не роблячи, перш ніж досягти червоної стежки, потрапивши на помаранчеву стежку.\

З (>, ми зменшуємо A і перенаправляти IP - Схід. Тут він вражає гілку: <. Для позитивного A ми продовжуємо помаранчеву стежку. Інакше ІС спрямовується на Північний Схід.

'*переміщує MP в B і зберігає A * C в B . Тут був (n-1)*(n-2)початковий вхід n. Потім IP повертається в початковий цикл і продовжує зменшуватися і множитися, поки A не досягне 0. (обчислення n-1!)

Примітка : У наступних циклах &зберігається значення від B у C , оскільки C має позитивне значення, яке зберігається в ньому зараз. Це має вирішальне значення для обчислювальної фактори.

Вихід:

Вихідні дані

Коли А досягає 0. Гілка натомість спрямовує IP по синьому шляху.

=*реверсує MP і зберігає значення B * C в A . Тоді IP виходить із шестикутника і знову входить на зелену стежку; виконання "%. Це переміщує MP в OUT і обчислює A mod IN , або (n-1!)² mod n.

Наведені нижче {"діють як неоперативні, оскільки вони скасовують один одного. !друкує остаточний висновок і *+'(виконуються до завершення: @.

Після виконання (з введенням 5) пам'ять виглядає так:

Пам'ять2

Прекрасні образи потоку управління були зроблені з використанням Timwi в Hexagony Coloror .

Дякую Мартіну Ендеру за генерування всіх зображень, оскільки я не міг зробити це на своєму ПК.


Що ви використовуєте для цих діаграм пам'яті? Я бачив Езотеричний IDE, але не міг змусити його працювати ...
NieDzejkob

@NieDzejkob вам краще попросити Мартіна в чаті, оскільки він все одно зробив їх для мене.
H.PWiz

@NieDzejkob Так, діаграма пам'яті можна експортувати з EsoIDE. chat.stackexchange.com/rooms/27364/…, якщо ви хочете ще поговорити про це.
Мартін Ендер

33

Морнінгтон Півмісяць , 2448 байт

Ми знову в Лондоні!

Take Northern Line to Bank
Take Circle Line to Bank
Take District Line to Parsons Green
Take District Line to Bank
Take Circle Line to Hammersmith
Take District Line to Upney
Take District Line to Hammersmith
Take Circle Line to Victoria
Take Victoria Line to Seven Sisters
Take Victoria Line to Victoria
Take Circle Line to Victoria
Take Circle Line to Bank
Take Circle Line to Hammersmith
Take Circle Line to Cannon Street
Take Circle Line to Hammersmith
Take Circle Line to Cannon Street
Take Circle Line to Bank
Take Circle Line to Hammersmith
Take Circle Line to Aldgate
Take Circle Line to Aldgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Aldgate
Take Circle Line to Hammersmith
Take District Line to Upminster
Take District Line to Hammersmith
Take Circle Line to Notting Hill Gate
Take Circle Line to Hammersmith
Take Circle Line to Notting Hill Gate
Take District Line to Upminster
Take District Line to Bank
Take Circle Line to Victoria
Take Circle Line to Temple
Take Circle Line to Aldgate
Take Circle Line to Aldgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Pinner
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Pinner
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Pinner
Take Metropolitan Line to Aldgate
Take Circle Line to Hammersmith
Take District Line to Upminster
Take District Line to Victoria
Take Circle Line to Aldgate
Take Circle Line to Victoria
Take Circle Line to Victoria
Take District Line to Upminster
Take District Line to Embankment
Take Circle Line to Embankment
Take Northern Line to Angel
Take Northern Line to Moorgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Aldgate
Take Circle Line to Aldgate
Take Circle Line to Cannon Street
Take District Line to Upney
Take District Line to Cannon Street
Take District Line to Acton Town
Take District Line to Acton Town
Take Piccadilly Line to Russell Square
Take Piccadilly Line to Hammersmith
Take Piccadilly Line to Russell Square
Take Piccadilly Line to Ruislip
Take Piccadilly Line to Ruislip
Take Metropolitan Line to Preston Road
Take Metropolitan Line to Aldgate
Take Circle Line to Aldgate
Take Circle Line to Cannon Street
Take Circle Line to Aldgate
Take Circle Line to Aldgate
Take Metropolitan Line to Preston Road
Take Metropolitan Line to Moorgate
Take Circle Line to Moorgate
Take Northern Line to Mornington Crescent

Timwi був таким добрим, щоб реалізувати станції управління потоком Templeі Angelв Esoteric IDE , а також додати вхідний і цілий аналіз для мовної специфікації.

Цей, мабуть, кращий для гольфу, ніж "Привіт, світ!", Тому що цього разу я написав сценарій CJam, щоб допомогти мені знайти найкоротший шлях між будь-якими двома станціями. Якщо ви хочете використовувати його (хоча я не знаю, чому хто-небудь хотів би ...), ви можете скористатися онлайн-перекладачем . Вставте цей код:

"Mornington Crescent"
"Cannon Street"
]qN/{'[/0=,}$:Q;{Q{1$#!}=\;_oNo'[/1>{']/0="[]"\*}%}%:R;NoQ{R\f{f{\#)}:+}:*},N*

Тут перші два рядки - це станції, які ви хочете перевірити. Крім того, вставте вміст цієї пастини у вікно введення.

Вихід покаже вам, які лінії доступні на двох станціях, а потім список усіх станцій, які з'єднують дві, відсортований за довжиною назв станцій. Це показує всі вони, тому що іноді краще використовувати довше ім’я, або тому, що це дозволяє коротша лінія, або тому, що станція особлива (наприклад, банк або храм), щоб ви хотіли її уникнути. Є деякі крайні випадки, коли дві станції не з'єднані жодною іншою станцією (зокрема, лінії метрополії та округи ніколи не перетинаються), і в цьому випадку вам доведеться з’ясувати щось інше. ;)

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

Одне питання полягає в тому, що петлі - це петлі "do-while", а зменшення і збільшення - дороге, тому я не можу легко обчислити (n-1)!(для n > 0). Натомість я обчислюю, n!а потім ділюся nнаприкінці. Я впевнений, що для цього є краще рішення.

Коли я почав писати це, я зрозумів, що зберігання -1в Хаммерсміті буде гарною ідеєю, щоб я міг знизитись дешевше, але врешті-решт це може коштувати дорожче, ніж заощаджено. Якщо я знайду терпіння повторити це, я, можливо, спробую просто продовжувати займатися -1в Upminster, щоб я міг використовувати Hammersmith для чогось більш корисного.


10
Чи закінчується Лондон turing?
Rohan Jhunjhunwala

1
@RohanJhunjhunwala певно
Мартін Ендер

Оце Так! Я люблю бачити добре продумані питання. Я особливо люблю бачити питання, де вам потрібно написати програму, щоб написати програму.
Rohan Jhunjhunwala

27

Брахілог (V2), 1 байт

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

Брахілог (V1), 2 байти

#p

Для цього використовується вбудований предикат #p - Prime, який обмежує його вхід простою кількістю.

Brachylog - моя спроба створити версію Prolog Code Golf, що є декларативним кодом для гольфу, що використовує зворотний трек і уніфікацію.

Альтернативне рішення без вбудованого: 14 байт

ybbrb'(e:?r%0)

Ось розбивка коду вище:

y            The list [0, …, Input]
bbrb         The list [2, …, Input - 1]
'(           True if what's in the parentheses cannot be proven; else false
     e           Take an element from the list [2, …, Input - 1]
     :?r%0       The remainder of the division of the Input but that element is 0
)

1
Можливо, ви захочете відредагувати Brachylog 2 версії цього повідомлення також і після публікації, коли синтаксис на байт коротший.

1
@ ais523 Щоправда, зроблено.
Фаталізувати

Чи відповідає відповідь Brachylog 2 на виклик?
Скотт Мілнер

1
@ScottMilner Так, але це прямо дозволено в цьому виклику: "На відміну від наших звичних правил,
Fatalize

26

Хаскелл, 49 байт

Використання xnor's Colarlary до теореми Вілсона :

main=do n<-readLn;print$mod(product[1..n-1]^2)n>0

Чи не було б це коротше зробити main=interact$\n-> ...?
Джон Дворак

2
Протирічливо, ні! Подумайте, що вам interact...readтам десь знадобиться , що робить це набагато довше, ніж просто readLn. Часто doпозначення можуть бути більш короткими, ніж ви могли очікувати, особливо коли альтернативою є лямбда.
Лінн

24

Лабіринт , 29 байт

1
?
:
}  +{%!@
(:'(
 } {
 :**

Читає ціле число зі STDIN та виводить ((n-1)!)^2 mod n. Теорема Вілсона досить корисна для цього завдання.

Програма починається в лівому верхньому куті, починаючи з 1цього, множивши верхню частину стека на 10 і додаючи 1. Це спосіб створення Лабіринту у великій кількості, але оскільки стеки Лабіринту заповнені нулями, кінцевий ефект є як би ми просто штовхнув 1.

?потім читає nзі STDIN і :дублює його. }зміщується nна допоміжний стек, який використовується в кінці для модуля. (потім декременти n, і ми готові приступити до обчислення факторної площі.

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

Бо n = 1, оскільки верхівка стека nзменшена, або 0, ми йдемо прямо вперед. Тоді ми потрапили в неоперацію 'з наступним указом, (який ставить нас на -1. Це негативно, тому повертаємо ліворуч, виконуючи +плюс ( -1 + 0 = -1), {щоб nповернутись із допоміжного стеку до основного та %модуля ( -1 % 1 = 0). Потім виводимо з !і закінчуємо з @.

Бо n > 1на другій :ми повертаємо праворуч. Потім ми перекладаємо }наш скопійований лічильник циклів на допоміжний стек, дублюємо :і множимо двічі **, перш ніж зміщувати лічильник назад {і зменшувати (. Якщо ми все ще позитивні, ми намагаємось повернути праворуч, але не можемо, тому Лабіринт змушує нас повернути ліворуч, продовжуючи цикл. В іншому випадку вершина стека - це наш лічильник циклів, який був зменшений до 0, який ми +додаємо до нашого обчисленого ((n-1)!)^2. Нарешті, ми nповертаємося назад з {потім модулем %, виводимо !і закінчуємо @.

Я сказав, що 'це не-оп, але його також можна використовувати для налагодження. Біжіть з -dпрапором, щоб побачити стан стека щоразу, коли 'передача передається!


2
Квадратура фабрики - це справді класна хитрість :)
Лінн

@Mauris Дякую! Мені потрібно дати кредит там, де це обумовлено - я вперше побачив хитрість, яку тут
Sp3000

5
Так, перша відповідь Лабіринту не написана мною! :)
Мартін Ендер

24

Утиліти Bash + GNU, 16

  • 4 байти збережено завдяки @Dennis

  • 2 байти збережено завдяки @Lekensteyn

factor|awk NF==2

Введення - це один рядок, узятий із STDIN. Вихід є порожнім рядком для фальси і не порожнім рядком для truthy. Наприклад:

$ ./pr.sh <<< 1
$ ./pr.sh <<< 2
2: 2
$ ./pr.sh <<< 3
3: 3
$ ./pr.sh <<< 4
$

2
Класно, дізнався про ще одне ядро. Ви можете зняти два символи, порахувавши кількість полів:factor|awk NF==2
Lekensteyn

@Lekensteyn - дякую - чомусь я пропустив ваш коментар :)
Digital Trauma

Я збирався розмістити щось дещо подібне, тільки довше і без AWK. Чудово зроблено.
Девід Конрад

21

Java, 126 121 байт

Я думаю, нам потрібна відповідь Java для табло ... так ось простий цикл пробного поділу:

class P{public static void main(String[]a){int i=2,n=Short.valueOf(a[0]);for(;i<n;)n=n%i++<1?0:n;System.out.print(n>1);}}

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

У розгорнутому вигляді:

class P{
    public static void main(String[]a){
        int i=2,n=Short.valueOf(a[0]);
        for(;i<n;)
            n=n%i++<1?0:n;
        System.out.print(n>1);
    }
}

Редагувати: Виправлено та перероблено Петром у коментарях. Дякую!


Баггі: він повідомляє, що 1це головне. В іншому випадку буде 4-значне заощадження, видаливши pта сказавшиfor(;i<n;)n=n%i++<1?0:n;System.out.print(n>0);
Пітер Тейлор

2
Ото class P{public static void main(String[]a){int i=2,n=Short.valueOf(a[0]);for(;i<n;)n=n%i++<1?0:n;System.out.print(n>1);}}роботи
Пітер Тейлор

6
зміна рядка 3 на 'long i = 2, n = Long.valueOf (a [0]); `не призводить до зміни довжини, а до ширшого діапазону дійсних входів.
Джеймс К Полк

4
Замість цього .valueOfви можете використовувати new, як в new Short(a[0]), або new Long(a[0]), що трохи коротше.
ECS

3
Ви можете зберегти 4 байти, використовуючи інтерфейс та скинувши publicмодифікатор.
RamenChef

18

Мозг-Флак , 112 108 байт

({}[()]){((({})())<>){{}<>(({}<(({}[()])()<>)>)<>)<>{({}[()]<({}[()]<({}())>)>{(<()>)}{})}{}{}}}<>{{}}([]{})

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

Як це працює

Спочатку перший стек буде містити додатне ціле n , другий стек буде порожнім.

Почнемо з декрементації n наступним чином.

(
  {}      Pop n.
  [()]    Yield -1.
)       Push n - 1.

n = 1

Якщо n = 1 дорівнює нулю, цикл while

{
  ((({})())<>)
  {
    {}<>(({}<(({}[()])()<>)>)<>)<>{({}[()]<({}[()]<({}())>)>{(<()>)}{})}{}{}
  }
}

пропускається повністю. Нарешті, решта код виконується.

<>    Switch to the second stack (empty).
{}    Pop one of the infinite zeroes at the bottom.
{<>}  Switch stacks while the top on the active stack is non-zero. Does nothing.
(
  []    Get the length of the active stack (0).
  {}    Pop another zero.
)     Push 0 + 0 = 0.

n> 1

Якщо n - 1 не дорівнює нулю, вводимо цикл, який n = 1 пропускає. Це не "справжній" цикл; код виконується лише один раз. Він досягає наступного.

{                   While the top of the active stack is non-zero:
  (
    (
      ({})                Pop and push n - 1.
      ()                  Yield 1.
    )                   Push n - 1 + 1 = n.
    <>                  Switch to the second stack. Yields 0.
  )                   Push n + 0 = n.
                      We now have n and k = n - 1 on the first stack, and n on
                      the second one. The setup stage is complete and we start
                      employing trial division to determine n's primality.
  {                   While the top of the second stack is non-zero:
    {}                  Pop n (first run) or the last modulus (subsequent runs),
                        leaving the second stack empty.
    <>                  Switch to the first stack.
    (
      (
        {}                  Pop n from the first stack.
        <
          (
            (
              {}              Pop k (initially n - 1) from the first stack.
              [()]            Yield -1.
            )               Push k - 1 to the first stack.
            ()              Yield 1.
            <>              Switch to the second stack.
          )               Push k - 1 + 1 = k on the second stack.
        >               Yield 0.
      )               Push n + 0 = n on the second stack.
      <>              Switch to the first stack.
    )               Push n on the first stack.
    <>              Switch to the second stack, which contains n and k.
                    The first stack contains n and k - 1, so it is ready for
                    the next iteration.
    {({}[()]<({}[()]<({}())>)>{(<()>)}{})}{}{}  Compute and push n % k.
  }               Stop if n % k = 0.
}               Ditto.

n% k обчислюється за допомогою алгоритму 42-байтового модуля з моєї відповіді на тест на подільність .

Нарешті, ми інтерпретуємо результати для визначення первинності n .

<>    Switch to the first stack, which contains n and k - 1, where k is the
      largest integer that is smaller than n and divides n evenly.
      If (and only if) n > 1 is prime, k = 1 and (thus) k - 1 = 0.
{     While the top of the first stack is non-zero:
  {}    Pop it.
}     This pops n if n is prime, n and k - 1 if n is composite.
(
  []    Yield the height h of the stack. h = 1 iff n is prime).
  {}    Pop 0.
)     Push h + 0 = h.

2
Вам не потрібно вставляти останні 0 на стек, оскільки трикутник 1 зверху достатній; таким чином можна зберегти два байти, видаливши останній {}.
Стівен Х.

1
Гм, я розірваний. З одного боку, питання говорить, що вихід повинен складатися виключно з правдивого або хибного значення і 1 0є двома значеннями. З іншого боку, ми приймаємо масиви до тих пір, поки мова вважає їх правдоподібними або хибними, а декілька елементів стека - це найближче, що Brain-Flak має до масивів. Можливо, варто взяти це до мета.
Денніс

Я 1 0посвідчився з творцем Brain-Flak, що є правдою. chat.stackexchange.com/transcript/message/32746241#32746241
Стівен Х.


17

R, 37 29 байт

n=scan();cat(sum(!n%%1:n)==2)

Використовує пробний поділ. scan()зчитує ціле число з STDIN і cat()записує в STDOUT.

Ми генеруємо вектор довжини, nщо складається з цілих чисел 1 до nмодуля n. Ми перевіряємо, чи кожний дорівнює 0, заперечуючи ( !), що повертає логічне значення, яке є істинним, коли число дорівнює 0, а помилкове, коли воно більше 0. Сума логічного вектора - це кількість дійсних елементів, а для простих чисел ми очікуємо єдиний ненульовий модуль дорівнює 1, і nтому ми очікуємо, що сума дорівнює 2.

Збережено 8 байт завдяки флоделю!


З ним f=function(x)sum(!x%%1:x)==2можна зробити в 28 байт.
Мутадор

2
@ AndréMuta Для цього завдання всі подання повинні бути повноцінними програмами, а не лише функціями. Дякую за пропозицію, хоча.
Олексій А.

17

TI-BASIC, 12 байт

2=sum(not(fPart(Ans/randIntNoRep(1,Ans

Досить прямо. randIntNoRep(дає випадкову перестановку всіх цілих чисел від 1 до Ans.

Це трохи згинає правила; оскільки списки в TI-BASIC обмежені 999 інтерпретованими нами елементами

припустимо, що вхід може зберігатися у вашому типі даних

що означає, що всі типи даних можуть вважати, що вони містять дані. ОП погоджується з таким тлумаченням.

Розчин 17 байт , який на самому ділі працює до 10 ^ 12 або так:

2=Σ(not(fPart(Ans/A)),A,1,Ans

@toothbrush TI-BASIC - це токенізована мова, тому кожен маркер тут - один байт, за винятком randIntNoRep(якого є два.
lirtosiast

+1 Ах, я ніколи раніше не бачив TL-BASIC. Дякуємо, що повідомили мені
зубна щітка

1
Хоча, це трохи несправедливо, чи не так ...? Я повинен написати мову для гольфу, для якої потрібно лише 1-4 байти (ідентифікатор питання), а потім параметри. Він вибере верхню відповідь на зрозумілій мові, виконає її (передаючи будь-які параметри) та поверне результат ... Цікаво, чи це порушує правила? :-)
Зубна щітка

@toothbrush На захист TI-BASIC: для інтерпретатора це не є більш несправедливим, ніж однозначні команди Pyth і CJam, а TI-BASIC - більш читабельний.
lirtosiast

1
Правда. Мені не подобаються такі мови, оскільки рішення майже в будь-якій іншій мові довші ... хоча я нещодавно побив CJam з VB6 ! : -]
Зубна щітка

15

PARI / GP, 21 байт

print(isprime(input))

Працює для смішно великих вкладів, адже саме така річ - те, для чого створено PARI / GP.


6
isprimeчи підтверджує первинність APR-CL, тому дуже сповільнюється, оскільки вхід стає дуже великим. ispseudoprime(input)робить ймовірний простий тест AES BPSW, який буде набагато швидшим для понад 100 цифр. Ще невідомі контрприклади після 35 років. Версія 2.1 та новіші версії Pari, починаючи з 2002 року, використовують інший метод, який може легко дати помилкові результати, але ніхто не повинен цим користуватися.
DanaJ

15

TI-BASIC, 24 байти

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

Відповідь Томаса Ква на це вище.

:Prompt N
:2
:While N≠1 and fPart(N/Ans
:Ans+1
:End
:N=Ans

Зразок:

N=?1009
                         1
N=?17
                         1
N=?1008
                         0
N=?16
                         0

Тепер повертається, 0якщо не прем'єр, або 1якщо він є.


3
Чи не квадратний корінь - це лише оптимізація, яка вам насправді не потрібна, щоб програма була правильною?
Мартін Ендер

Навіщо вам ділити на два?
Геобіт

Я завжди люблю відповіді TI-BASIC.
Грант Міллер

15

Стек котів , 62 + 4 = 66 байт

*(>:^]*(*>{<-!<:^>[:((-<)<(<!-)>>-_)_<<]>:]<]]}*<)]*(:)*=<*)>]

Потрібно запускати -lnпрапори командного рядка (отже, +4 байти). Відбитки 0для складених чисел та 1для простих чисел.

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

Я думаю, що це перша нетривіальна програма Stack Cats.

Пояснення

Швидке введення Stack Cats:

  • Stack Cats працює на нескінченній стрічці стеків, головка стрічки спрямована на поточний стек. Кожна стопка спочатку заповнюється нескінченною кількістю нулів. Я, як правило, ігнорую ці нулі у своїй формулюванні, тому коли я кажу "нижня частина стека", я маю на увазі найменше ненульове значення, а якщо я кажу "стек порожній", я маю на увазі, що на ньому є лише нулі.
  • Перед запуском програми a -1висувається на початковий стек, а потім весь вхід висувається поверх цього. У цьому випадку через -nпрапор вхід зчитується у вигляді десяткового цілого числа.
  • В кінці програми поточний стек використовується для виводу. Якщо є -1внизу, воно буде проігноровано. Знову ж таки, завдяки -nпрапору, значення зі стека просто друкуються у вигляді десяткових цілих чисел, розділених рядками.
  • Stack Cats - це зворотна мова програми: кожен фрагмент коду можна скасувати (без Stack Cats відстежувати явну історію). Більш конкретно, щоб повернути будь-який фрагмент коду, ви просто відобразили його, наприклад, <<(\-_)став (_-/)>>. Ця мета дизайну встановлює досить суворі обмеження щодо того, які види операторів і конструкцій керуючого потоку існують у мові та які функції ви можете обчислити в глобальній пам'яті.
  • На додаток до цього, кожна програма Stack Cats повинна бути самосиметричною. Ви можете помітити, що це не стосується вищевказаного вихідного коду. Це те, для чого -lпрапор: він неявно відображає код зліва, використовуючи перший символ у центрі. Отже, власне програма:

    [<(*>=*(:)*[(>*{[[>[:<[>>_(_-<<(-!>)>(>-)):]<^:>!->}<*)*[^:<)*(>:^]*(*>{<-!<:^>[:((-<)<(<!-)>>-_)_<<]>:]<]]}*<)]*(:)*=<*)>]
    

Ефективне програмування за допомогою всього коду є нетривіальним та неінтуїтивним, але ще не зрозуміли, як людина може це зробити. Ми грубо змусили таку програму для більш простих завдань, але не змогли б дістатись до неї вручну. На щастя, ми знайшли основну схему, яка дозволяє ігнорувати половину програми. Хоча це, безумовно, неоптимально, на даний момент це єдиний відомий спосіб ефективно програмувати в Stack Cats.

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

[<(...)*(...)>]

Коли програма запускається, стрічка стека виглядає приблизно так (для введення 4, скажімо):

     4    
... -1 ...
     0
     ^

У [русі верхній частині стека вліво (і стрічка голови разом) - ми називаємо це «штовхаючи». І <рухає стрічку головою поодинці. Отже, після перших двох команд у нас виникла така ситуація:

...   4 -1 ...
    0 0  0
    ^

Тепер (...)цикл - це цикл, який можна використовувати досить легко як умовний: цикл вводиться та залишається лише тоді, коли вершина поточного стеку є додатною. Оскільки наразі це нуль, ми пропускаємо всю першу половину програми. Тепер команда центру є *. Це просто XOR 1, тобто перемикає найменш значущий біт верхньої частини стека, і в цьому випадку перетворює 0на 1:

... 1 4 -1 ...
    0 0  0
    ^

Тепер ми зустрічаємо дзеркальне зображення (...). На цей раз у верхній частині стека є позитивним , і ми робимо ввести код. Перш ніж ми розберемося, що відбувається всередині дужок, дозвольте мені пояснити, як ми завершимо завершення: ми хочемо переконатися, що в кінці цього блоку ми знову будемо мати головку стрічки на позитивному значенні (щоб цикл закінчується після однієї ітерації і використовується просто як лінійна умовна умова), що стек праворуч містить висновок, а права стека, що містить а -1. Якщо це так, ми залишаємо цикл, >переміщуємося на вихідне значення і ]натискаємо на нього, -1щоб у нас був чистий стек для виводу.

Ось це. Тепер усередині дужок ми можемо робити все, що завгодно, щоб перевірити первинність, якщо ми гарантуємо, що в кінці ми встановимо речі, як описано в попередньому абзаці (що можна легко зробити, коли натискання та переміщення головки стрічки). Я вперше спробував вирішити проблему з теоремою Вілсона, але закінчився набагато більше 100 байт, тому що обчислення факторних квадратів насправді є досить дорогим у Stack Cats (принаймні, я не знайшов короткий шлях). Тому я пішов із пробним поділом, і це справді виявилося набагато простіше. Давайте розглянемо перший лінійний біт:

>:^]

Ви вже бачили дві з цих команд. Крім того, :підміняє два перших значення поточного стеку, а ^XOR - друге значення на верхнє значення. Це робить :^загальний шаблон для дублювання значення в порожній стеці (ми витягуємо нуль у верхній частині значення, а потім перетворюємо нуль у 0 XOR x = x). Отже після цього розділу наш стрічка виглядає так:

         4    
... 1 4 -1 ...
    0 0  0
         ^

Алгоритм пробного поділу, який я застосував, не працює для введення даних 1, тому в цьому випадку нам слід пропустити код. Ми можемо легко зіставити 1з 0і всім іншим позитивних значень з *, так ось як ми це робимо:

*(*...)

Тобто ми переходимо 1в 0, пропустити велику частину коду , якщо ми дійсно 0, але всередині ми негайно скасувати , *так що ми отримуємо наше вхідне значення назад. Нам потрібно ще раз переконатися, що ми закінчимося позитивним значенням наприкінці дужок, щоб вони не почали циклічно. Всередині умовного способу переміщуємо один стек прямо з, >а потім починаємо основний цикл пробного поділу:

{<-!<:^>[:((-<)<(<!-)>>-_)_<<]>:]<]]}

Брекети (на відміну від дужок) визначають різний тип циклу: це цикл do-while, тобто він завжди працює щонайменше за одну ітерацію. Інша відмінність - умова завершення: при введенні в цикл Stack Cat запам’ятовує верхнє значення поточного стека ( 0у нашому випадку). Потім цикл буде працювати, поки це ж значення знову не з’явиться в кінці ітерації. Це зручно для нас: у кожній ітерації ми просто обчислюємо залишок наступного потенційного дільника і переміщуємо його на цей стек, з якого ми починаємо цикл. Коли ми знайдемо дільник, залишок - 0і петля зупиняється. Ми спробуємо дільники, починаючи з, n-1а потім зменшуючи їх 1. Це означає, що а) ми знаємо, що це закінчиться, коли ми дійдемо1найпізніше та б) ми можемо визначити, чи є число простим чи ні, перевіривши останній дільник, який ми спробували (якщо він 1є простим, інакше - ні).

Давайте перейдемо до цього. На початку є короткий лінійний розділ:

<-!<:^>[:

Ви знаєте, чим зараз займається більшість цих речей. Нові команди - -і !. Stack Cats не має операторів збільшення або зменшення. Однак він має -(заперечення, тобто помножити на -1) і !(порозрядно НЕ, тобто помножити на -1і зменшити). Вони можуть бути об'єднані у приріст !-, або у зменшення -!. Таким чином, ми декрементуємо копію nзверху -1, потім робимо ще одну копію nна стеку зліва, а потім дістаємо новий пробний дільник і поміщаємо її внизу n. Отже, на першій ітерації ми отримуємо це:

      4       
      3       
... 1 4 -1 ...
    0 0  0
      ^

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

((-<)<(<!-)>>-_)

Це обчислення модуля. Оскільки петлі закінчуються на позитивних значеннях, ідея полягає в тому, щоб почати з -nі кілька разів додавати до нього пробний дільник, dпоки ми не отримаємо додатне значення. Як тільки ми це робимо, ми віднімаємо результат, dі це дає нам залишок. Тут складний біт полягає в тому, що ми не можемо просто поставити -nна вершину стека і запустити цикл, який додає d: якщо верхня частина стека негативна, цикл не буде введено. Такі обмеження оборотної мови програмування.

Отже, щоб обійти цю проблему, ми починаємо з nвершини стека, але заперечуємо її лише на першій ітерації. Знову ж таки, це звучить простіше, ніж виявляється ...

(-<)

Коли вершина стека є позитивною (тобто лише на першій ітерації), ми заперечуємо її -. Однак ми не можемо просто зробити це, (-)тому що тоді ми не залишатимемо цикл, поки -не буде застосовано двічі. Таким чином, ми переміщуємо одну клітинку, що залишилася, <тому що ми знаємо, що є позитивне значення (the 1). Гаразд, тепер ми надійно заперечували nза першою ітерацією. Але у нас є нова проблема: головка стрічки зараз знаходиться в іншому положенні за першою ітерацією, ніж у всіх інших. Нам потрібно закріпити це, перш ніж рухатись далі. Наступний <рухає головку стрічки вліво. Ситуація на першій ітерації:

        -4       
         3       
...   1  4 -1 ...
    0 0  0  0
    ^

А на другій ітерації (пам’ятайте, що ми додали dодин раз -n):

      -1       
       3       
... 1  4 -1 ...
    0  0  0
    ^

Наступний умовний спосіб знову об'єднує ці шляхи:

(<!-)

При першій ітерації головка стрічки вказує на нуль, тому це повністю пропускається. При подальших ітераціях голова стрічки вказує на одиницю, тому ми виконуємо це, рухаємося вліво і збільшуємо туди клітинку. Оскільки ми знаємо, що клітина починається з нуля, вона завжди буде позитивною, тому ми можемо залишити цикл. Це гарантує, що ми завжди закінчуємо два стеки зліва від основного стеку і тепер можемо повернутися назад >>. Потім в кінці петлі модуля робимо -_. Ви вже знаєте -. _полягає в відніманні , що ^повинен XOR: якщо вершина стека aі значення Нижче bвін замінює aз b-a. Так як ми перший заперечується , aхоча, -_замінює aз b+a, тим самим додавшиd в наш загальний обсяг.

Після закінчення циклу (ми досягли позитивного) значення, стрічка виглядає приблизно так:

        2       
        3       
... 1 1 4 -1 ...
    0 0 0  0
        ^

Найбільш лівим значенням може бути будь-яке додатне число. Насправді, це кількість повторень мінус одна. Зараз є ще один короткий лінійний біт:

_<<]>:]<]]

Як я вже говорив раніше, нам потрібно відняти результат, dщоб отримати фактичний залишок ( 3-2 = 1 = 4 % 3), тому ми просто робимо _ще раз. Далі нам потрібно очистити стек, який ми нарощували ліворуч: коли ми спробуємо наступний дільник, він знову повинен бути нульовим, щоб перша ітерація спрацювала. Тож ми переміщаємось туди і підштовхуємо це позитивне значення до іншого стека помічників, <<]а потім повертаємось назад до нашого операційного стека з іншим >. Ми тягнемо вгору dз :і штовхати його назад на -1з , ]а потім ми переміщаємо залишок на наш умовний стек з <]]. Ось і закінчується цикл пробного поділу: це триває, поки ми не отримаємо нульовий залишок, і в цьому випадку стек зліва міститьnнайбільший дільник (крім n).

Після закінчення циклу, *<перед тим, як ми знову з’єднаємось із шляхами із введенням , існує лише певний час 1. *Просто перетворює нуль в 1, який ми будемо мати потребу в трохи, а потім ми перейдемо до дільнику з <(так , що ми знаходимося на тому ж стеку , як і для введення 1).

На даний момент це допомагає порівнювати три різні види входів. По-перше, особливий випадок, n = 1коли ми не зробили жодного з цих пробних підрозділів:

         0    
... 1 1 -1 ...
    0 0  0
         ^

Тоді, у нашому попередньому прикладі n = 4, складене число:

    2           
    1    2 1    
... 1 4 -1 1 ...
    0 0  0 0
         ^

І, нарешті, n = 3просте число:

    3           
    1    1 1    
... 1 3 -1 1 ...
    0 0  0 0
         ^

Таким чином, для простих чисел у нас є 1стек, а для складених чисел у нас або число 0чи додатнє число більше, ніж 2. Ми перетворюємо цю ситуацію на необхідну 0чи 1наступну частину коду:

]*(:)*=<*

]просто штовхає це значення праворуч. Тоді *використовується для того, щоб значно спростити умовну ситуацію: переключивши найменш значущий біт, ми перетворимось 1( перетворимось на ) 0, 0(складемо) у позитивне значення 1, а всі інші позитивні значення залишаться позитивними. Тепер нам просто потрібно розрізняти 0і позитивне. Ось тут ми використовуємо інше (:). Якщо верхня частина стека є 0(а вхід був простим), це просто пропускається. Але якщо верхня частина стека є позитивною (а вхід був складеним числом), це поміняє її на 1, так що тепер у нас є 0композитний та1для прайменів - лише два різних значення. Звичайно, вони протилежні тому, що ми хочемо вивести, але це легко фіксується з іншим *.

Тепер все, що залишилося, - це відновити візерунок стеків, очікуваний нашим оточуючим фреймом: голова стрічки на позитивному значенні, результат у верхній частині стека праворуч і одиничний -1у стеку праворуч від цього . Це для чого =<*. =підміняє вершини двох сусідніх стеків, тим самим переміщуючи -1праворуч від результату, наприклад для введення 4знову:

    2     0       
    1     3       
... 1 4   1 -1 ...
    0 0 0 0  0
          ^

Тоді ми просто рухаємося ліворуч <і перетворюємо цей нуль в один із *. І це все.

Якщо ви хочете заглибитись у те, як працює програма, ви можете скористатися параметрами налагодження. Або додайте -dпрапор і вставте "там, де ви хочете побачити поточний стан пам’яті, наприклад, як це , або використовуйте -Dпрапор, щоб отримати повний слід всієї програми . Крім того, ви можете використовувати Езотерицид Timwi, який включає інтерпретатор Stack Cats з поетапним налагодженням.


3
>:^]повинен бути офіційним логотипом Stack Cats
Алекс А.

14

Haskell, 54 байти

import Data.Numbers.Primes
main=readLn>>=print.isPrime

Нічого багато для пояснення.


1
Такий же результат можна досягти (хоча і дуже неефективно) без зовнішніх бібліотек, використовуючи теорему Вілсона:main=do n<-readLn;print$n>1&&mod(product[1..n-1]+1)n<1
Лінн

9
Навіть ми можемо зробити коротше: main=do n<-readLn;print$mod(product[1..n-1]^2)n>0це 49 байт.
Лінн

4
@Mauris: Приємно. Будь ласка, опублікуйте це як окрему відповідь.
німі

14

Ruby, 15 + 8 = 23 байти

p$_.to_i.prime?

Проба зразка:

bash-4.3$ ruby -rprime -ne 'p$_.to_i.prime?' <<< 2015
false

Хе-хе, я знав, що в Рубі десь буде вбудований будинок, але я не міг потрудитися його шукати, тому відповів у С1.
Рівень Рівер Сент

@steveverrill, я знав це, тому що це була велика допомога для проекту Euler.
манатура

14

JavaScript, 39 36 байт

Збережено 3 байти завдяки ETHproductions:

for(i=n=prompt();n%--i;);alert(1==i)

Відображає істину для простих, інакше помилкових.

Цикл for тестує кожне число i від n-1, поки я не дільник. Якщо перший знайдений дільник 1, то це просте число.


Попереднє рішення (39 байт):

for(i=n=prompt();n%--i&&i;);alert(1==i)

Як залишився непотрібний тест:

for(i=2,n=prompt();n%i>0&&i*i<n;i++);alert(n%i>0) //49: Simple implementation: loop from 2 to sqrt(n) to test the modulo.
for(i=2,n=prompt();n%i>0&&i<n;i++);alert(n==i)    //46: Replace i*i<n by i<n (loop from 2 to n) and replace n%i>0 by n==i
for(i=2,n=prompt();n%i&&i<n;i++);alert(n==i)      //44: Replace n%i>0 by n%i
for(i=2,n=prompt();n%i&&i++<n;);alert(n==i)       //43: Shorten loop increment
for(i=n=prompt();n%--i&&i>0;);alert(1==i)         //41: Loop from n to 1. Better variable initialization.
for(i=n=prompt();n%--i&&i;);alert(1==i)           //39: \o/ Replace i>0 by i

Я розмістив лише 39 байт рішення, тому що найкраща відповідь на JavaScript - це вже 40 байт.


2
Ласкаво просимо до головоломки програмування та коду для гольфу!
Денніс

2
Чудова відповідь! &&iЧи не робить нічого в цій програмі, так що ви можете видалити його.
ETHproductions

слід додати n>1остаточну умову, якщо ви не хочете 1бути прем'єр-міністром.
Тит

1
@Titus Якщо вхідний 1цикл for for зробить n%--iодин раз: 1%0повертає NaNта зупиняє цикл. Коли alertвиклик iвже дорівнює 0тому 1==iповертається false.
Хеді

2
i <2 (та деякий текст)
Шейнтод

13

Равлики, 122

Введення даних повинно бути одиничним. Цифри можуть бути будь-яким поєднанням символів, крім нових рядків.

^
..~|!(.2+~).!~!{{t.l=.r=.}+!{t.!.!~!{{r!~u~`+(d!~!.r~)+d~,.r.=.(l!~u~)+(d!~l~)+d~,.l.},l=(.!.)(r!~u~)+(d!~!.r~)+d~,.r.!.

У цій 2D мові відповідності шаблону стан програми складається виключно з поточного розташування сітки, набору відповідних комірок та позиції в коді шаблону. Також незаконно їздити на збірну площу. Це складно, але можливо зберігати та отримувати інформацію. Обмеження щодо подорожі на збірну клітинку можна подолати за допомогою зворотного відстеження, телепортування ( t) та тверджень ( =, !), які залишають сітку без змін після завершення.

Факторизація 25

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

Код з примітками:

^                         Match only at the first character
..~ |                     Special case to return true for n=2
!(.2 + ~)                 Fail for even numbers
. !~                      Match 1st character and fail for n=1
!{                        If the bracketed pattern matches, it's composite.
  (t. l=. r=. =(.,~) )+   Teleport to 1 or more chars and match them (blue in graphic)
                          Only teleport to ones that have an unmatched char on each side.
                          The =(.,~) is removed in the golfed code. It forces the
                          teleports to proceed from left to right, reducing the
                          time from factorial to exponential.
  !{                      If bracketed pattern matches, factorization has failed.
    t . !. !~             Teleport to a square to the left of a blue square (yellow in diagram)
    !{                    Bracketed pattern verifies equal number of spaces to
                          the left or right of a blue square.
      {              
        (r!~ u~)+         Up...
        (d!~!. r~)+       Right...
        d~,               Down...
        . r . =.          Move 1 to the right, and check that we are not on the edge;
                          otherwise d~, can fall off next iteration and create and infinite loop
        (l!~ u~)+         Up...
        (d!~ l~)+         Left...
        d ~,              Down...
        . l .             Left 1
      } ,                 Repeat 0 or more times
      l  =(. !.)          Check for exactly 1 unused char to the left
      (r!~ u~)+           Up...
      (d!~!. r~)+         Right...
      d ~,                Down...
      . r . !.
    }
  }
}

13

C, 67 байт

i,n;main(p){for(scanf("%d",&i),n=i;--i;p=p*i*i%n);putchar(48+p%n);}

Друкує !1(значення фальси, за визначенням Пітера Тейлора ), 0 якщо (n-1)!^2 == 0 (mod n)та 1інше.

EDIT : Після деякої дискусії в чаті, puts("!1"+p%n)здається, вона вважається трохи хитрою, тому я її замінив. Результат на один байт довший.

EDIT : Виправлено для великих входів.

Коротші рішення

56 байт : Як рекомендовано в коментарях pawel.boczarski, я міг би взяти вкладку уніар, прочитавши кількість аргументів командного рядка:

p=1,n;main(i){for(n=--i;--i;p=p*i*i%n);putchar(48+p%n);}

виклик програми типу

$ ./a.out 1 1 1 1 1
1                        <-- as 5 is prime

51 байт : Якщо ви дозволяєте "виводити" за допомогою зворотних кодів:

p=1,n;main(i){for(n=--i;--i;p=p*i*i%n);return p%n;}

Ваше рішення можна скоротити, використовуючи унарне представлення (кількість аргументів командного рядка), як у моєму рішенні. Ви можете поголити деякі байти під час виклику scanf.
pawel.boczarski

puts("!1"+p%n)Як ви могли коли-небудь зробити a+bдля char*цінностей?
Ерік Аутгольфер

Якщо рядок "!1"починається з адреси a, то a+1ви знайдете рядок "1".
Лінн

@Lynn О, я думав , що це було для конкатенації (так, краще залишити , що до strcat(const char*,const char*).)
Ерік Outgolfer

Ви можете змінитись p=p*i*i%nдоp*=i*i%n
Альберт Реншо

12

Python 3, 59 байт

Тепер використовується input()замість аргументів командного рядка. Завдяки @Beta Decay

n=int(input())
print([i for i in range(1,n)if n%i==0]==[1])

Використовувати вкладення input()було б набагато коротше
Beta Decay

Дякую, я вже писав із використанням input (), але забув оновити свою відповідь. Знову дякую!
uno20001

4
52 байт: n=m=int(input()),print(all(n%m for m in range(2,n)))
Джон Ліон

1
Ти серйозно. Витратьте 25 зайвих символів для кульгавого квадратичного прискорення? Тут ми ненавидимо байти . Ми проводимо кожну годину, хвилину та секунду свого життя, позбавляючись дев'ятнадцятого байта. (Жартую. Але ми не робимо оптимізації часу, що збільшують тривалість програми.)
CalculatorFeline

2
Використовуйте n%i<1замість цього.
Ерік Аутгольфер

12

APL, 40 13 байт

2=+/0=x|⍨⍳x←⎕

Trial розподіл з тим же алгоритмом , як мій R відповідь . Задамо xна вхід з STDIN ( ) і отримати залишок для xподіленій на кожному число від 1 до x. Кожен залишок порівнюється з 0, що дає нам вектор одиниць і нулів, що вказують, на які цілі числа ділиться x. Це підсумовується за допомогою +/отримання кількості дільників. Якщо це число рівно 2, це означає, що єдині дільники на 1 і x, таким чином, xє простими.


12

Пітон 2, 44

P=n=1
exec"P*=n*n;n+=1;"*~-input()
print P%n

Як і відповідь Python Sp3000 , але уникає збереження введення шляхом підрахунку змінної nвід 1до вхідного значення.


12

Мета + програмування шаблонів на C ++. 166 131 119 байт.

Код складається, якщо константа є простим, а не компілюється, якщо складений або 1.

template<int a,int b=a>struct t{enum{x=t<a,~-b>::x+!(a%b)};};
template<int b>struct t<b,0>{enum{x};};
int _[t<1>::x==2];

(всі нові рядки, крім остаточного, видаляються у "реальній" версії).

Я вважаю, що "невдача компілювати" - це значення повернення фальси для мови метапрограмування. Зауважте, що він не посилається (тому, якщо ви будете годувати його основним, ви отримаєте помилки посилання) як повноцінна програма C ++.

Значення для тестування - ціле число в останньому "рядку".

живий приклад .

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