Хотите верьте, хотите нет, у нас пока нет задачи по коду для простого теста на примитивность . Хотя это, возможно, и не самая интересная задача, особенно для «обычных» языков, она может быть нетривиальной во многих языках.
Списки кода Rosetta представлены языками идиоматических подходов к тестированию простоты: один использует тест Миллера-Рабина, а другой - пробное деление . Однако «самый идиоматический» часто не совпадает с «самым коротким». Чтобы сделать Programming Puzzles и Code Golf доступным сайтом для Code Golf, эта задача состоит в том, чтобы составить каталог кратчайшего подхода на каждом языке, похожего на «Hello, World!» и Гольф, ты идеальный для хорошего! ,
Кроме того, возможность реализации теста на простоту является частью нашего определения языка программирования , поэтому эта задача также будет служить каталогом проверенных языков программирования.
задача
Напишите полную программу, которая, учитывая строго положительное целое число n в качестве входных данных, определяет, является ли n простым, и печатает истинное или ложное значение соответственно.
Для этой задачи целое число является простым, если оно имеет ровно два строго положительных делителя. Обратите внимание, что это исключает 1 , который является его единственным строго положительным делителем.
Ваш алгоритм должен быть детерминированным (т. Е. Производить правильный вывод с вероятностью 1) и теоретически должен работать для сколь угодно больших целых чисел. На практике вы можете предположить, что входные данные могут храниться в вашем типе данных, если программа работает для целых чисел от 1 до 255.
вход
Если ваш язык способен читать из STDIN, принимать аргументы командной строки или любую другую альтернативную форму ввода данных пользователем, вы можете прочитать целое число как его десятичное представление, унарное представление (используя выбранный вами символ), байтовый массив (большой или little endian) или однобайтовый (если это ваш самый большой тип данных в вашем языке).
Если (и только если) ваш язык не может принять какой-либо пользовательский ввод, вы можете жестко закодировать ввод в вашей программе.
В этом случае жестко запрограммированное целое число должно быть легко заменяемым. В частности, оно может появиться только в одном месте во всей программе.
Для оценки выставьте программу, соответствующую вводу 1 .
Выход
Вывод должен быть записан в STDOUT или ближайшую альтернативу.
Если возможно, вывод должен состоять исключительно из истинного или ложного значения (или его строкового представления), за которым может следовать одна новая строка.
Единственным исключением из этого правила является постоянный вывод интерпретатора вашего языка, который не может быть подавлен, например приветствие, цветовые коды ANSI или отступы.
Дополнительные правила
Речь идет не о поиске языка с кратчайшим подходом к первичному тестированию, а о поиске кратчайшего подхода в каждом языке. Поэтому ни один ответ не будет помечен как принятый.
Материалы на большинстве языков будут оцениваться в байтах в соответствующей существующей кодировке, обычно (но не обязательно) UTF-8.
Например, язык Piet будет оцениваться в коде, что является естественным выбором для этого языка.
Некоторые языки, такие как папки , немного сложнее оценить. Если вы сомневаетесь, пожалуйста, спросите на Meta .
В отличие от наших обычных правил, не стесняйтесь использовать язык (или языковую версию), даже если он новее этой задачи. Если кто-то хочет злоупотребить этим, создавая язык, в котором пустая программа выполняет тест на простоту, то поздравляю с подготовкой очень скучного ответа.
Обратите внимание, что должен быть переводчик, чтобы представление можно было проверить. Разрешается (и даже поощряется) самостоятельно писать этот переводчик для ранее не реализованного языка.
Если выбранный вами язык является тривиальным вариантом другого (потенциально более популярного) языка, у которого уже есть ответ (например, диалекты BASIC или SQL, оболочки Unix или тривиальные производные Brainfuck, такие как Headsecks или Unary), рассмотрите возможность добавления примечания к существующему ответу, который такое же или очень похожее решение также является самым коротким на другом языке.
Встроенные функции для проверки простоты будут разрешены. Эта задача предназначена для каталогизации кратчайшего возможного решения на каждом языке, поэтому, если использовать встроенный язык на вашем языке короче, сделайте это.
Если они не были отменены ранее, применяются все стандартные правила игры в гольф , включая http://meta.codegolf.stackexchange.com/q/1061 .
В качестве примечания, пожалуйста, не понижайте скучные (но действительные) ответы на языках, где не так много в гольфе; они все еще полезны для этого вопроса, так как он пытается собрать каталог настолько полно, насколько это возможно. Тем не менее, делайте в первую очередь upvote ответы на языках, где автор фактически должен был приложить усилия для игры в гольф.
Каталог
Фрагмент стека в нижней части этого поста создает каталог из ответов а) в виде списка кратчайшего решения для каждого языка и б) в качестве общей таблицы лидеров.
Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:
## 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
Ответы:
Привет, мир! 13
источник
Гексагония , 29 байт
Читаемая версия этого кода:
Пояснение: Он проверяет, существует ли число от 2 до n-1, которое делит n.
Инициализация:
Запишите n в одну ячейку памяти и n-1 в другую:
Особый случай n = 1:
Выведите 0 и завершите
Петля
Рассчитайте n% a и уменьшите a. Завершить, если a = 1 или n% a = 0.
Случай а = 1:
Увеличьте 0 до 1, распечатайте его и завершите. (Указатель инструкций работает в направлении NE и проходит от восточного угла к юго-западному углу. И $ гарантирует, что он игнорирует следующую команду)
Случай% n = 0:
Выведите 0 и завершите (указатель инструкции запускается SW и переходит в верхнюю часть к @
источник
Гексагония ,
218925855 байтОбратите внимание: этот ответ был жестко побежден Etoplay решением с длиной стороны 4 .
Первая в истории нетривиальная (т.е. нелинейная) программа Hexagony! Он основан на том же квадратичном факторе, что и ответ Sp3000 на Лабиринт . Начав с шестигранника размера 10, мне удалось сжать его до размера 5. Однако я смог повторно использовать некоторый дублирующий код, и в коде все еще есть куча неиспользуемых операций, поэтому размер 4 мог бы просто быть возможным
объяснение
Чтобы разобраться в коде, нам сначала нужно его развернуть. Hexagony добавляет любой исходный код к следующему центрированному шестиугольному числу с помощью no-ops (
.
), то есть61
. Затем он переставляет код в обычный шестиугольник соответствующего размера:Это довольно сильно связано с пересечением и перекрытием путей выполнения и множественных указателей инструкций (IP). Чтобы объяснить, как это работает, давайте сначала посмотрим на версию без заглядывания, где поток управления не проходит через границы, используется только один IP, а пути выполнения максимально просты:
Примечание: приведенный выше код начинается с выполнения первой строки, в которой нет никаких операций. Затем, когда IP-адрес достигает северо-восточного края, он переходит в самый левый угол (
)
), где начинается фактический код.Прежде чем мы начнем, несколько слов о разметке памяти Hexagony. Это немного похоже на ленту Брейнфука на стероидах. На самом деле это не лента, а сама шестиугольная сетка (бесконечная), где каждое ребро имеет целочисленное значение, которое изначально равно 0 (а в отличие от стандартного Brainfuck значения являются знаковыми целыми числами произвольной точности). Для этой программы мы будем использовать четыре ребра:
Мы будем вычислять факториал на ребро А , отсчитывать наш вход на края С и сохранить другую копию ввода (для по модулю) на ребра D . B используется как временное ребро для вычислений.
Указатель памяти (MP) начинается с края A и указывает на север (это важно для перемещения MP вокруг). Теперь вот первый бит кода:
)
увеличивает ребро A в1
качестве основы факториала.}
заставляет MP поворачивать направо, то есть двигаться к краю C (указывая на северо-восток). Здесь мы читаем ввод как целое число с?
. Затем мы сделаем еще один поворот направо на край D с}
.=
переворачивает MP, таким образом, что она указывает на вершину совместно с C .&
копирует значение из C (вход) в D - значение копируется слева, потому что текущее значение не положительное (ноль). Наконец, мы заставляем MP повернуть налево назад к C с помощью{
.Далее,
<
это технически ветвь, но мы знаем, что текущее значение положительно, поэтому IP всегда будет направлен в сторону>
. Ветвь хит от боковых действует как зеркало, таким образом, что IP -по горизонтали снова движется, по направлению к(
, который уменьшает значение в C .Следующая ветвь,
<
на самом деле, сейчас ветка. Вот как мы переходим от циклаn-1
к1
. В то время как текущее значение в C положительно, IP поворачивает направо (чтобы выполнить цикл). Как только мы достигнем нуля, он повернет налево.Давайте посмотрим на цикл "тело". Это
|
простые зеркала,>
и<
они снова используются как зеркала. Это означает, что фактическое тело цикла сводится к}
перемещает MP к ребру B ,=
меняет направление на вершину ABC .)
увеличивает значение: это актуально только для первой итерации, где значение B по-прежнему равно нулю: мы хотим убедиться, что оно положительное, чтобы следующая инструкция&
копировала правого соседа, т.е. A , то есть текущее значение факториала вычисление, в B .}
затем перемещает MP к A ,=
полностью изменяет его, чтобы стоять перед общей вершиной.*
умножает оба соседей, то есть края B и C и сохраняет результат в . Наконец, у нас есть еще один, чтобы вернуться к C , по-прежнему лицом к вершине ABC .}=
Я надеюсь , что вы можете увидеть , как это вычисляет факториал
n-1
в A .Итак, теперь мы сделали это, счетчик цикла в C равен нулю. Мы хотим возвести в квадрат факториал и затем взять по модулю входные данные. Вот что делает этот код:
Поскольку C равен нулю,
&
копирует левый сосед, т.е. факториала в . переходит к B и сохраняет произведение двух копий факториала (т.е. квадрат) в B . возвращается к С , но не меняет MP. Мы знаем , что текущее значение теперь положительное, поэтому ввод копий из D в C . МП в обратном направлении вправо, т.е. на . Помните, квадрат факториала в B , а вход в C . Так что вычисляет , именно то, что мы ищем.}=*
{
&
'
%
(n-1)!^2 % n
!
выводит результат в виде целого числа (0 или 1) и@
завершает программу.Ладно, но это была не изгнанная версия. А как насчет версии для гольфа? Вам нужно знать еще две вещи о гексагонии:
]
и на предыдущий с помощью[
. (Вы также можете выбрать определенный с помощью#
, но это в другой раз.)Есть также несколько новых команд в нем:
\
и/
зеркала , как|
и~
умножает текущее значение на-1
.Так как же версия без гольфа переходит в версию с гольфом? Линейный код настройки
)}?}=&{
и базовая структура цикла можно найти здесь:Теперь тело цикла пересекает ребра несколько раз, но самое главное, фактические вычисления передаются на предыдущий IP (который начинается в левом углу, двигаясь на северо-восток):
После отскока от ветви в направлении юго-востока, IP оборачивается по краю до двух
=
в верхнем левом углу (которые вместе являются запретными), а затем отскакивает от/
.~
Инвертирует знак текущего значения, что важно для последующих итераций. IP снова обходит тот же край и, наконец, попадает[
туда, где управление передается другому IP.Теперь выполняется этот,
~}=)&}=*}
который отменяет отрицание, а затем просто запускает тело цикла без гольфа (минус=
). Наконец, он попадает к тому,]
какие руки возвращаются к исходному IP. (Обратите внимание, что в следующий раз, когда мы выполним этот IP-адрес, он начнется с того места, где остановился, поэтому сначала он достигнет угла. Нам нужно, чтобы текущее значение было отрицательным, чтобы IP-адрес мог вернуться обратно к северо-западному краю. вместо юго-восточного.)Как только исходный IP-адрес возобновляет управление, он отскакивает от
\
, выполняет оставшиеся,=
а затем нажимает>
для подачи в следующую итерацию цикла.Теперь действительно безумная часть: что происходит, когда цикл заканчивается?
IP перемещается на северо-восток от
<
и оборачивается к северо-восточной диагонали. Таким образом, он попадает в тот же путь выполнения, что и тело цикла (&}=*}]
). Что на самом деле довольно круто, потому что это именно тот код, который мы хотим выполнить на данном этапе, по крайней мере, если мы добавим еще один=}
(потому что}=}
это эквивалентно{
). Но как это фактически не входит в более ранний цикл снова? Потому что]
меняется на следующий IP, который теперь является (пока что не использованным) IP, который начинается в верхнем правом углу, двигаясь на юго-запад. Оттуда IP продолжается вдоль края, переносится в верхний левый угол, перемещается вниз по диагонали, отскакивает от|
и заканчивается в момент@
выполнения последнего бита линейного кода:(
)(
Конечно, это не работает - мне пришлось добавить,(
потому что)
он уже был там.)Фу ... какой беспорядок ...
источник
1
) . О чем1
ты там говоришь?)
Обыкновение быть1
.Pyth, 4 байта
Отпечатки
True
илиFalse
.источник
P_
Сетчатка , 16 байт
Попробуйте онлайн!
Начнем с классики: обнаружение простых чисел с помощью регулярного выражения . Ввод должен быть дан в унарном виде , используя любой повторяющийся печатный символ. Набор тестов включает в себя преобразование из десятичного в унарный для удобства.
Программа Retina, состоящая из одной строки, обрабатывает эту строку как регулярное выражение и печатает количество совпадений, найденных во входных данных, что будет
0
для составных чисел и1
простых чисел.Предварительный просмотр гарантирует, что ввод не является составным: при обратном отслеживании будут проверяться все возможные подстроки (не менее 2 символов)
(..+)
, а предварительный просмотр пытается сопоставить остальную часть ввода, повторяя то, что было записано здесь. Если это возможно, это означает, что вход имеет делитель больше 1, но меньше, чем он сам. Если это так, то отрицательный прогноз приводит к сбою сопоставления. Для простых чисел такой возможности нет, и матч продолжается.Единственная проблема заключается в том, что этот запрос также принимает
1
, поэтому мы исключаем это, сопоставляя по крайней мере два символа с..
.источник
CJam, 4 байта
CJam имеет встроенный оператор для тестирования простоты.
источник
limp
pimp
мой cjampimp
объективно больше сутенераl~mp
q
читает строку ввода,i
анализирует ее как целое число иmp
является встроенной. В CJam есть две группы встроенных двухсимвольных: начинаются «расширенные» и начинаютсяe
«математические»m
HTML + CSS, 254 + n макс * 28 байт
Мы можем проверить простоту с помощью регулярных выражений. Mozilla имеет
@document
, который определяется как:Для фильтрации элементов с помощью CSS на основе текущего URL. Это один проход, поэтому мы должны сделать два шага:
1. Получение информации
Самый короткий путь, который я могу понять, чтобы получить ввод и перенести его на URL, это
GET
форма с флажками. Для регулярного выражения нам просто нужна уникальная строка для подсчета появлений.Итак, начнем с этого (61 байт):
Мы получили два уникальных
<p>
s, чтобы указать, является ли введенное число простым (1) или нет (0). Мы также определяем форму и ее действие.Далее следуют n max флажков с тем же именем (n max * 28 байт):
Затем следует элемент submit (34 байта):
2. Показать ответ
Нам нужен CSS (159 байт), чтобы выбрать
<p>
для отображения (1 или 0):»Попробуйте это на codepen.io (только Firefox)
источник
Помогите, WarDoq! 1 байт
Выходы 1, если вход простое, 0 в противном случае.
источник
Гексагония , 28 байт
Так как Etoplay абсолютно обеспокоил меня по этому вопросу , я почувствовал, что должен переиграть его единственный другой ответ .
Попробуйте онлайн!
Я использую теорему Вильсона, как Мартин сделал в своем ответ : Учитывая
n
, I выход(n-1!)² mod n
Вот это программа развернулась:
И вот читаемая версия:
Объяснение:
Программа имеет три основных этапа: инициализация , факториал и вывод .
Модель памяти гексагонии представляет собой бесконечную гексагональную сетку. Я использую 5 ячеек памяти, как показано на этой диаграмме:
Я буду ссылаться на эти местоположения (и целые числа, хранящиеся в них) по их меткам на этой диаграмме.
Инициализация:
Указатель инструкций ( IP ) начинается в верхнем левом углу и идет на восток. Указатель памяти ( MP ) начинается с IN .
Во-первых,
?
читает число из ввода и сохраняет его в IN . IP остается на голубом пути, отражаемый\
. Последовательность"&(
перемещает MP назад и влево (к A ), копирует значение из IN в A и уменьшает его.Затем IP выходит из одной стороны шестиугольника и снова входит в другую сторону (на зеленый путь). Он выполняет
'+
который перемещает MP в B и копирует то , что было в . перенаправляет IP на запад.<
Факториал:
Я вычисляю факториал особым образом, так что возведение в квадрат это легко. Я храню
n-1!
в B и C следующим образом.Указатель инструкций начинается с синего пути в восточном направлении.
='
меняет направление МП и перемещает его назад к C . Это эквивалентно тому, чтобы{=
иметь,=
где это было полезно позже.&{
копирует значение из к C , затем перемещает MP обратно в . Затем IP следует по зеленому пути, ничего не делая, прежде чем достигнуть красного пути, ударившись о оранжевый путь.\
С помощью
(>
мы уменьшаем A и перенаправляем IP East. Здесь он поражает ветку:<
. Для положительного А мы продолжаем идти по оранжевой дорожке. В противном случае IP направляется на северо-восток.'*
перемещает MP в B и сохраняет A * C в B . Это(n-1)*(n-2)
где первоначальный вклад былn
. IP - затем поступает обратно в исходную петлю и продолжает декремента и не умножая до А достигает0
. (вычисленияn-1!
)NB . В следующих циклах
&
сохраняет значение из B в C , так как C имеет положительное значение, сохраненное в нем. Это очень важно для вычисления факториала.Выход:
Когда А достигает
0
. Вместо этого ветвь направляет IP по синему пути.=*
реверсирует MP и сохраняет значение B * C в A . Затем IP выходит из шестиугольника и снова входит в зеленый путь; выполнение"%
. Это перемещает MP в OUT и вычисляет A mod IN или(n-1!)² mod n
.Следующее
{"
действует как запрет, так как они отменяют друг друга.!
печатает окончательный вывод и*+'(
выполняются до завершения:@
.После выполнения (с вводом
5
) память выглядит так:Прекрасные изображения потока управления были сделаны с использованием Hexagony Coloror Тимви .
Спасибо Мартину Эндеру за создание всех изображений, так как я не смог сделать это на своем ПК.
источник
Морнингтон Полумесяц , 2448 байт
Мы вернулись в Лондон!
Timwi был очень любезен, чтобы реализовать станции управления потоками
Temple
иAngel
в Esoteric IDE, а также добавить ввод и анализ целочисленных значений в спецификацию языка.Этот, вероятно, лучше, чем «Hello, World!», Потому что на этот раз я написал сценарий CJam, чтобы помочь мне найти кратчайший путь между любыми двумя станциями. Если вы хотите использовать его (хотя я не знаю, почему кто-то захочет ...), вы можете воспользоваться онлайн-переводчиком . Вставьте этот код:
Здесь первые две строки - это станции, которые вы хотите проверить. Также вставьте содержимое этой вставки в окно ввода.
Вывод покажет вам, какие линии доступны на этих двух станциях, а затем список всех станций, которые соединяют эти две станции, отсортированные по длине названий станций. Он показывает их все, потому что иногда лучше использовать более длинное имя, либо потому, что оно позволяет использовать более короткую линию, либо потому, что станция особенная (например, Банк или Храм), так что вы хотите ее избежать. Есть некоторые крайние случаи, когда две станции не соединены какой-либо другой станцией (в частности, линии Метрополитен и Район никогда не пересекаются), и в этом случае вам придется выяснить что-то еще. ;)
Что касается фактического кода MC, он основан на квадратично-факториальном подходе, как и многие другие ответы, потому что MC имеет умножение, деление и по модулю. Также я подумал, что один цикл будет удобен.
Одна из проблем заключается в том, что циклы являются циклами do-while, а уменьшение и увеличение является дорогостоящим, поэтому я не могу легко вычислить
(n-1)!
(дляn > 0
). Вместо этого я вычисляю,n!
а затем делюn
на в конце. Я уверен, что есть лучшее решение для этого.Когда я начал писать это, я подумал, что хранение
-1
в Hammersmith было бы хорошей идеей, поэтому я могу уменьшить цену дешевле, но в итоге это может стоить больше, чем сэкономлено. Если я найду терпение, чтобы повторить это, я мог бы попытаться просто держать-1
в Upminster, чтобы я мог использовать Hammersmith для чего-то более полезного.источник
Brachylog (V2), 1 байт
Попробуйте онлайн!
Брахилог (V1), 2 байта
При этом используется встроенный предикат
#p - Prime
, который ограничивает его ввод простым числом.Brachylog - моя попытка создать версию Prolog для Code Golf, которая является декларативным языком для гольфа Code, в котором используется возврат и объединение.
Альтернативное решение без встроенного: 14 байтов
Вот разбивка кода выше:
источник
Haskell, 49 байтов
Используя следствие xnor к теореме Вильсона :
источник
main=interact$\n-> ...
?interact...read
где-то там, что делает его намного длиннее, чем простоreadLn
. Зачастуюdo
нотация может быть более краткой, чем вы могли бы ожидать, особенно когда альтернативой является лямбда.Лабиринт , 29 байт
Читает целое число из STDIN и выводит
((n-1)!)^2 mod n
. Теорема Вильсона довольно полезна для этой задачи.Программа начинается в верхнем левом углу, начиная с
1
которого умножает вершину стека на 10 и добавляет 1. Это способ Лабиринта строить большие числа, но, поскольку стеки Лабиринта заполнены нулями, конечный эффект такой, как если бы мы просто нажал 1.?
затем читаетn
из STDIN и:
дублирует его.}
переходитn
на вспомогательный стек, который будет использоваться в конце для модуля.(
затем декрементыn
, и мы готовы начать вычисление квадрата факториала.Наш второй
:
(дубликат) находится на стыке, и здесь вступают в игру функции управления потоком данных Лабиринта. На перекрестке после выполнения инструкции, если вершина стека положительна, мы поворачиваем направо, для отрицательного мы поворачиваем налево, а для нуля - прямо. Если вы попытаетесь повернуть, но ударите стену, Лабиринт заставит вас повернуть в другом направлении.Поскольку
n = 1
, поскольку вершина стекаn
уменьшается, или0
мы идем прямо вперед. Затем мы нажимаем на запрет,'
за которым следует еще один декрет,(
который ставит нас на-1
. Это отрицательно, поэтому мы поворачиваем налево, выполняя+
plus (-1 + 0 = -1
),{
чтобы перейтиn
от вспомогательного стека к основному и%
по модулю (-1 % 1 = 0
). Затем мы выводим с!
и заканчиваем с@
.На
n > 1
втором:
мы повернем направо. Затем мы перемещаем}
наш скопированный счетчик циклов во вспомогательный стек, дублируем:
и умножаем дважды**
, прежде чем сдвинуть счетчик назад{
и уменьшить его(
. Если мы все еще уверены, что мы пытаемся повернуть направо, но не можем, поэтому Лабиринт заставляет нас повернуть налево, продолжая цикл. В противном случае вершина стека - это наш счетчик цикла, который был уменьшен до 0, который мы+
добавляем к нашему вычисленному((n-1)!)^2
. Наконец, мыn
вернемся назад{
по модулю%
, выводим!
и завершаем работу@
.Я сказал, что
'
это не работает, но его также можно использовать для отладки. Запуск с-d
флагом, чтобы увидеть состояние стека каждый раз, когда'
передается!источник
Утилиты Bash + GNU, 16
4 байта сохранены благодаря @Dennis
2 байта сохранены благодаря @Lekensteyn
Ввод - одна строка, взятая из STDIN. Вывод - пустая строка для фальси и непустая строка для истины. Например:
источник
factor|awk NF==2
Java,
126121 байтЯ думаю, нам нужен ответ Java для табло ... так вот простой цикл пробного деления:
Как обычно для Java, требование «полной программы» делает это намного больше, чем было бы, если бы это была функция, в основном из-за
main
сигнатуры.В развернутом виде:
Редактировать: Исправлено и изменено Петром в комментариях. Спасибо!
источник
1
это главное. В противном случае можно было бы сэкономить 4 символа, убравp
и сказавfor(;i<n;)n=n%i++<1?0:n;System.out.print(n>0);
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);}}
работает.valueOf
вы можете использоватьnew
, как вnew Short(a[0])
, илиnew Long(a[0])
, что немного короче.public
модификатор.Brain-Flak ,
112108 байтПопробуйте онлайн!
Как это устроено
Первоначально первый стек будет содержать положительное целое число n , второй стек будет пустым.
Начнем с уменьшения n следующим образом.
n = 1
Если n = 1 равно нулю, цикл while
полностью пропущен Наконец, оставшийся код выполняется.
n> 1
Если n - 1 не равно нулю, мы входим в цикл, который n = 1 пропускает. Это не «настоящий» цикл; код выполняется только один раз. Достигается следующее.
n% k вычисляется с использованием 42-байтового алгоритма модуля из моего ответа теста делимости .
Наконец, мы интерпретируем результаты, чтобы определить первичность n .
источник
{}
.1 0
представляет собой два значения. С другой стороны, мы принимаем массивы до тех пор, пока язык считает их правдивыми или ложными, а множественные элементы стека - самая близкая вещь, которую Brain-Flak имеет к массивам. Может быть стоит принять это к мета.1 0
это правда. chat.stackexchange.com/transcript/message/32746241#32746241R,
3729 байтИспользует пробное деление.
scan()
читает целое число из STDIN иcat()
записывает в STDOUT.Мы генерируем вектор длины,
n
состоящий из целых чисел от 1 доn
по модулюn
. Мы проверяем, равно ли каждое из них 0, с помощью negating (!
), которое возвращает логическое значение, которое истинно, когда число равно 0, и ложно, когда оно больше 0. Сумма логического вектора - это число истинных элементов, и для простых чисел мы ожидаем единственные ненулевые модули равны 1, иn
поэтому мы ожидаем, что сумма будет равна 2.Сохранено 8 байтов благодаря flodel!
источник
f=function(x)sum(!x%%1:x)==2
его помощью можно сделать это за 28 байтов.TI-BASIC, 12 байтов
Довольно просто.
randIntNoRep(
дает случайную перестановку всех целых чисел от 1 доAns
.Это немного нарушает правила; потому что списки в TI-BASIC ограничены 999 элементами, которые я интерпретировал
Это означает, что можно предположить, что все типы данных соответствуют входным данным. ОП согласен с этой интерпретацией.
Раствор 17 байт , который на самом деле работает до 10 ^ 12 или так:
источник
randIntNoRep(
двух.PARI / GP, 21 байт
Работает на смехотворно большие входы, потому что именно такие вещи предназначены для PARI / GP.
источник
isprime
делает APR-CL доказательством первичности, поэтому немного замедляется, поскольку входные данные становятся очень большими.ispseudoprime(input)
выполняет вероятный первичный тест AES BPSW, который будет намного быстрее для более чем 100 цифр. До сих пор нет известных контрпримеров после 35 лет. Версия 2.1 и более ранние версии Pari, выпущенные до 2002 года, используют другой метод, который может легко дать ложные результаты, но никто не должен использовать это.TI-BASIC, 24 байта
Обратите внимание, что программы TI-Basic используют систему токенов, поэтому подсчет символов не возвращает действительное значение байта программы.
Upvote Томас Ква ответ , это лучше.
Образец:
Теперь возвращает,
0
если не простое число, или1
если это так.источник
Стека кошек , 62 + 4 = 66 байт
Должен запускаться с
-ln
флагами командной строки (следовательно, +4 байта). Принты0
для составных чисел и1
простых чисел.Попробуйте онлайн!
Я думаю, что это первая нетривиальная программа Stack Cats.
объяснение
Краткое введение в Stack Cats:
-1
помещается в начальный стек, а затем весь ввод помещается поверх этого. В этом случае из-за-n
флага входные данные читаются как десятичное целое число.-1
внизу есть значок, он будет проигнорирован. Опять же, из-за-n
флага значения из стека просто печатаются как десятичные целые числа, разделенные переводом строки.<<(\-_)
становитесь(_-/)>>
. Эта цель разработки накладывает довольно жесткие ограничения на то, какие операторы и конструкции потоков управления существуют в языке, и какие функции можно вычислять в состоянии глобальной памяти.В довершение всего, каждая программа Stack Cats должна быть самосимметричной. Вы можете заметить, что это не относится к приведенному выше исходному коду. Вот для чего этот
-l
флаг: он неявно отражает код слева, используя первый символ для центра. Следовательно, фактическая программа:Эффективное программирование всего кода крайне нетривиально и не интуитивно понятно, и еще не совсем понятно, как человек может это сделать. Мы грубо форсировали такую программу для более простых задач, но не смогли бы подобраться к ней вручную. К счастью, мы нашли базовый шаблон, который позволяет игнорировать одну половину программы. Хотя это, безусловно, неоптимально, в настоящее время это единственный известный способ эффективного программирования в Stack Cats.
Таким образом, в этом ответе шаблон указанного шаблона выглядит следующим образом (есть некоторые различия в том, как он выполняется):
Когда программа запускается, стековая лента выглядит так (например, для ввода
4
):В
[
движении верхней части стека влево (и лента головы вместе) - мы называем это «толкая». И<
движется лента в одиночку. Итак, после первых двух команд мы получили следующую ситуацию:Теперь
(...)
это цикл, который можно довольно легко использовать в качестве условного: цикл вводится и остается только тогда, когда вершина текущего стека положительна. Поскольку в настоящее время он равен нулю, мы пропускаем всю первую половину программы. Сейчас центр команды есть*
. Это простоXOR 1
, то есть он переключает младший значащий бит вершины стека, и в этом случае превращает0
в1
:Теперь мы сталкиваемся с зеркальным отображением
(...)
. На этот раз в верхней части стека является положительным , и мы делаем ввести код. Прежде чем мы рассмотрим, что происходит в скобках, позвольте мне объяснить, как мы будем заключать в конце: мы хотим убедиться, что в конце этого блока у нас снова будет положительное значение на ленте (так, чтобы цикл завершается после одной итерации и используется просто как линейный условный оператор), что стек справа содержит вывод и что стек справа от этого содержит a-1
. Если это так, мы покидаем цикл,>
перемещаемся к выходному значению и]
помещаем его в-1
так, чтобы у нас был чистый стек для вывода.Ничего не поделаешь. Теперь внутри скобок мы можем делать все, что захотим, чтобы проверить первичность, при условии, что мы гарантируем, что все настроено, как описано в предыдущем параграфе в конце (что может быть легко сделано с некоторым толчком и движением ленты). Сначала я попытался решить проблему с помощью теоремы Уилсона, но в итоге получилось более 100 байтов, потому что факториальное вычисление в квадрате на самом деле довольно дорого в Stack Cats (по крайней мере, я не нашел короткого пути). Так что вместо этого я пошел с пробным разделением, и это действительно оказалось намного проще. Давайте посмотрим на первый линейный бит:
Вы уже видели две из этих команд. Кроме того,
:
меняются два верхних значения текущего стека и^
XORs второе значение в верхнее значение. Это создает:^
общий шаблон для дублирования значения в пустом стеке (мы вытягиваем ноль поверх значения, а затем превращаем ноль в0 XOR x = x
). Итак, после этого раздел нашей ленты выглядит так:Алгоритм пробного деления, который я реализовал, не работает для ввода
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
. Итак, на первой итерации мы получаем это:На последующих итерациях
3
завещание будет заменено следующим делителем теста и т. Д. (Тогда как две копииn
всегда будут иметь одинаковое значение в этой точке).Это вычисление по модулю. Поскольку циклы заканчиваются на положительных значениях, идея состоит в том, чтобы начинать
-n
и многократно добавлять пробный делительd
к нему, пока мы не получим положительное значение. Как только мы это сделаем, мы вычтем результат из,d
и это даст нам остаток. Сложность в том, что мы не можем просто поместить-n
вершину стека и запустить цикл, который добавляетd
: если вершина стека отрицательна, цикл не будет введен. Таковы ограничения обратимого языка программирования.Поэтому, чтобы обойти эту проблему, мы начинаем с
n
вершины стека, но отрицаем ее только на первой итерации. Опять же, это звучит проще, чем оказывается ...Когда вершина стека положительна (т. Е. Только на первой итерации), мы ее отрицаем
-
. Тем не менее, мы не можем просто сделать,(-)
потому что тогда мы не будем выходить из цикла, пока не-
будет применен дважды. Таким образом, мы перемещаем одну ячейку влево,<
потому что мы знаем, что там есть положительное значение1
. Хорошо, теперь мы надежно отрицаемn
первую итерацию. Но у нас есть новая проблема: головка ленты на первой итерации теперь находится в другом положении, чем на любой другой. Нам нужно закрепить это, прежде чем мы пойдем дальше. Следующее<
перемещает головку ленты влево. Ситуация на первой итерации:И на второй итерации (помните, что мы добавили
d
один раз-n
сейчас):Следующее условие снова объединяет эти пути:
На первой итерации головка ленты указывает на ноль, поэтому это полностью пропускается. На последующих итерациях головка ленты указывает на единицу, поэтому мы выполняем это, перемещаемся влево и увеличиваем там ячейку. Поскольку мы знаем, что ячейка начинается с нуля, теперь она всегда будет положительной, поэтому мы можем выйти из цикла. Это гарантирует, что мы всегда получим два стека слева от основного стека и теперь можем вернуться назад
>>
. Затем в конце цикла по модулю мы делаем-_
. Вы уже знаете-
._
заключается в вычитании , что^
должен XOR: если вершина стекаa
и значение Нижеb
он заменяетa
сb-a
. Так как мы первый отрицается ,a
хотя,-_
заменяетa
сb+a
, тем самым добавивd
в наш текущий итог.После завершения цикла (мы достигли положительного значения) лента выглядит так:
Самое левое значение может быть любым положительным числом. На самом деле это число итераций минус одна. Теперь есть еще один короткий линейный бит:
Как я уже говорил ранее, нам нужно вычесть результат из,
d
чтобы получить фактический остаток (3-2 = 1 = 4 % 3
), поэтому мы просто сделаем_
еще раз. Далее нам нужно очистить стек, который мы увеличивали слева: когда мы пробуем следующий делитель, он снова должен быть равен нулю, чтобы первая итерация работала. Таким образом, мы перемещаемся туда и помещаем это положительное значение в другой стек помощников,<<]
а затем возвращаемся в наш операционный стек с другим>
. Мы вытягиваемd
с:
и возвращаем его обратно на-1
с,]
а затем перемещаем остаток в наш условный стек с<]]
. Это конец цикла пробного деления: это продолжается до тех пор, пока мы не получим нулевой остаток, и в этом случае стек слева содержитn
Наибольший делитель (кромеn
).После того, как цикл заканчивается, мы просто
*<
соединяем пути с входом1
снова. Он*
просто превращает ноль в a1
, который нам понадобится чуть позже, и затем мы переходим к делителю с помощью<
(так что мы находимся в том же стеке, что и для ввода1
).На данный момент это помогает сравнить три различных вида входных данных. Во-первых, особый случай,
n = 1
когда мы не делали ничего из того, что делали в пробном подразделении:Тогда в нашем предыдущем примере
n = 4
составное число:И, наконец,
n = 3
простое число:Так что для простых чисел у нас есть
1
в этом стеке, а для составных чисел у нас0
либо положительное число, либо больше, чем2
. Мы превращаем эту ситуацию в0
или, что1
нам нужно, с помощью следующего финального фрагмента кода:]
просто толкает это значение вправо. Затем*
используются для упрощения условной ситуации значительно: переключая значащий бит, мы переходим1
(прайм) в0
,0
(композит) в положительное значение1
, а все остальные положительные значения по- прежнему будут оставаться положительными. Теперь нам просто нужно различать0
положительное. Вот где мы используем другое(:)
. Если вершина стека0
(и вход был простым), это просто пропускается. Но если вершина стека положительна (а входное значение было составным числом), это заменяет его на1
, так что теперь мы имеем0
для составного и1
для простых чисел - только два разных значения. Конечно, они противоположны тому, что мы хотим вывести, но это легко исправить с помощью другого*
.Теперь осталось только восстановить шаблон стеков, ожидаемый нашей окружающей средой: ленточная головка с положительным значением, результат в верхней части стека справа и один
-1
в стеке справа от этого . Это для чего=<*
.=
меняет местами вершины двух соседних стеков, тем самым перемещая-1
вправо от результата, например, для ввода4
снова:Затем мы просто двигаемся влево
<
и превращаем этот ноль в единицу с*
. И это все.Если вы хотите глубже изучить работу программы, вы можете воспользоваться опциями отладки. Либо добавьте
-d
флаг и вставьте"
туда, где вы хотите видеть текущее состояние памяти, например, как это , или используйте-D
флаг, чтобы получить полный след всей программы . В качестве альтернативы вы можете использовать EsotericIDE от Timwi, который включает в себя интерпретатор Stack Cats с пошаговым отладчиком.источник
>:^]
должен быть официальным логотипом Stack CatsHaskell, 54 байта
Ничего особенного объяснить.
источник
main=do n<-readLn;print$n>1&&mod(product[1..n-1]+1)n<1
main=do n<-readLn;print$mod(product[1..n-1]^2)n>0
это 49 байтов.Рубин, 15 + 8 = 23 байта
Образец прогона:
источник
JavaScript,
3936 байтСохранено 3 байта благодаря продуктам ETH:
Отображает true для простого числа, false в противном случае.
Цикл for проверяет каждое число i от n-1 до делителя i . Если первый найденный делитель равен 1, то это простое число.
Предыдущее решение (39 байт):
Как был оставлен ненужный тест:
Я разместил только 39-байтовое решение, потому что лучший ответ JavaScript был уже 40 байт.
источник
&&i
самом деле ничего не делает в этой программе, так что вы можете удалить его.n>1
к последнему условию, хотя, если вы не хотите1
быть основным.1
для цикла for будет выполненn%--i
один раз:1%0
возвращаетNaN
и останавливает цикл. Когдаalert
вызываетсяi
уже равно0
так1==i
возвращаетсяfalse
.Улитки, 122
Ввод должен быть дан в унарном формате. Цифры могут быть любым сочетанием символов, кроме символов новой строки.
В этом языке сопоставления двухмерных шаблонов состояние программы состоит только из текущего местоположения сетки, набора ячеек, которые были сопоставлены, и положения в коде шаблона. Также незаконно путешествовать на подобранный квадрат. Это сложно, но можно хранить и извлекать информацию. Ограничение на перемещение в согласованную ячейку может быть преодолено путем обратного отслеживания, телепортации (
t
) и утверждений (=
,!
), которые оставляют сетку неизмененной после завершения.Факторизация для нечетного составного числа начинается с выделения некоторого набора взаимно несмежных ячеек (синий на диаграмме). Затем из каждой желтой ячейки программа проверяет наличие одинакового количества не синих ячеек по обе стороны от соседней синей ячейки, перемещаясь туда и обратно между двумя сторонами. Диаграмма показывает этот шаблон для одной из четырех желтых ячеек, которые необходимо проверить.
Аннотированный код:
источник
C 67 байт
Печатает
!1
(значение Фальси, по определению Питера Тейлора ),0
если(n-1)!^2 == 0 (mod n)
и1
иначе.РЕДАКТИРОВАТЬ : После некоторого обсуждения в чате,
puts("!1"+p%n)
кажется , кажется немного обманом, поэтому я заменил его. Результат на один байт длиннее.РЕДАКТИРОВАТЬ : Исправлено для больших входов.
Более короткие решения
56 байт : как рекомендовано в комментариях pawel.boczarski, я мог бы получить ввод в унарном виде, прочитав количество аргументов командной строки:
вызывая программу как
51 байт : если вы разрешите «вывод» с помощью кодов возврата:
источник
puts("!1"+p%n)
Как вы могли бы сделатьa+b
дляchar*
ценностей?"!1"
начинается с адресаa
, тоa+1
вы найдете строку"1"
.strcat(const char*,const char*)
.)p=p*i*i%n
наp*=i*i%n
Python 3, 59 байт
Теперь использует
input()
вместо аргументов командной строки. Благодаря @Beta Decayисточник
input()
будет намного корочеn=m=int(input())
,print(all(n%m for m in range(2,n)))
n%i<1
вместо этого.APL,
4013 байтTrial деление с тем же алгоритмом , как мой R ответ . Мы назначаем
x
входные данные из STDIN (⎕
) и получаем остаток дляx
деления на каждое целое число от 1 доx
. Каждый остаток сравнивается с 0, что дает нам вектор единиц и нулей, указывающих, какие целые числа делятсяx
. Это суммируется с помощью,+/
чтобы получить количество делителей. Если это число равно 2, это означает, что единственными делителями являются 1 иx
, и, таким образом,x
является простым.источник
Python 2, 44
Как и в ответе Python на Sp3000 , но избегает сохранения входных данных, считая переменную
n
от1
входного значения.источник
Шаблон метапрограммирования C ++.
166131119 байт.Код компилируется, если константа простое, и не компилируется, если составная или 1.
(все переводы строк, кроме финального, исключены в «реальной» версии).
Я полагаю, что «ошибка компиляции» является ошибочным возвращаемым значением для языка метапрограммирования. Обратите внимание, что он не связывает (поэтому, если вы передадите ему простое число, вы получите ошибки связывания) как полноценная программа на C ++.
Значение для проверки является целым числом в последней «строке».
живой пример .
источник