Это число факториал?


38

Задание

Принимая в качестве входных данных натуральное число, ваша задача состоит в том, чтобы вывести истинное или ложное значение в зависимости от того, является ли ввод факториалом какого-либо натурального числа. Вы можете предположить, что введенный номер всегда будет в диапазоне номеров, поддерживаемых вашим языком, но вы не должны злоупотреблять типами собственных чисел, чтобы тривиализировать проблему .

Стандартные лазейки применяются.


вход

Вам будет дано натуральное число (типа Integerили аналогичного).

Вы можете принимать входные данные любым способом, за исключением того, что он входит в предопределенную переменную. Чтение из файла, консоли, диалоговое окно ( prompt), поле ввода и т.д. допускается. Ввод в качестве аргумента функции также допускается!


Выход

Ваша программа должна выводить истинное или ложное значение в зависимости от того, является ли введенное число факториалом какого-либо натурального числа.

Убедитесь, что ваши значения truey / falsey согласуются для всех входных данных, т. Е. Если вы используете пару 1 и 0 для обозначения значений truey и falsey соответственно, то ваша программа должна вывести 1 для всех входных данных, которые должны иметь истинные значения, и 0 для все входы, которые должны иметь ложные значения.

Вы можете получать вывод любым способом, кроме записи в переменную. Запись в файл, консоль, экран и т. Д. Разрешена. Функция также returnразрешена!

Ваша программа не должна выдавать ошибки для любого ввода!


Тестовые случаи

Input     Output

1         Truthy (0! or 1!)
2         Truthy (2!)
3         Falsey
4         Falsey
5         Falsey
6         Truthy (3!)
7         Falsey
8         Falsey
24        Truthy (4!)
120       Truthy (5!)

Критерий победы

Это , поэтому выигрывает самый короткий код в байтах!


2
Если язык поддерживает только числа в диапазоне {0,1}, могу ли я ожидать, что ввод будет всегда 1?
eush77

11
@ eush77 Злоупотребление типами собственных чисел для упрощения задачи по умолчанию запрещено.
Деннис

1
это 4! правда?
Tuskiomi

Вопрос: Почему вы не используете значения по умолчанию для ввода / вывода?
CalculatorFeline

Ответы:


37

Брахилог , 1 байт

Попробуйте онлайн!

объяснение

является встроенным, который утверждает следующее соотношение: его вывод является факториалом его ввода. Мы просто даем ему заданный вывод и видим, будет ли он успешным с переменным вводом.


6
@BetaDecay Это потому, что это так, как это печатается в Прологе (это связано с тем, что true.это утверждение, а trueне)
Fatalize

6
Это тривиальное решение, но оно умное из-за того, как работает пролог.
Esolanging Fruit


17
Сначала пользовательские языки, затем пользовательские кодировки ... код гольф мертв.
Александр - восстановите Монику

13
@ Александр Пользовательские кодировки не имеют отношения к любой проблеме, о которой вы говорите. Вместо этого я мог бы использовать любую «существующую» кодировку, и она все равно была бы 1 байтом. Это было бы гораздо менее читабельным.
Роковая


19

Желе , 4 байта

Œ?IE

Не самый короткий ответ Jelly, но он довольно эффективен.

Попробуйте онлайн!

Как это работает

Œ?IE  Main link. Argument: n

Œ?    Yield the n-th permutation of the positive integers, without the sorted tail.
      For 120, this yields [5, 4, 3, 2, 1], the tail being [6, 7, 8, ...].
  I   Increments; compute all forward differences.
      For 120, this yields [-1, -1, -1, -1].
   E  Check if all differences are equal.

2
Потому что мы, разработчики кода, заботимся об эффективности.
Okx

12
Это значительное улучшение сложности за счет одного байта, и это умное использование встроенного, если можно так выразиться. ¯ \ _ (ツ) _ / ¯
Деннис

Интересно, что это возвращает true для 0, в то время как трехбайтовый ответ @ LeakyNun, хотя в целом намного медленнее, правильно возвращает false для 0. Нужны ли дополнительные байты для возврата false для 0 в ответе с эффективным временем выполнения?
Deadcode

@Deadcode Проверка на 0 потребует двух дополнительных байтов. Если вы не уверены, содержит ли ОП определение «натуральные числа» 0 или нет. Тестовые случаи не ...
Деннис

17

ECMAScript Regex, 733+ 690+ 158 119 118 (117🐌) байтов

Мой интерес к регулярным выражениям возник с новой силой после более чем 4,5 лет бездействия. Поэтому я отправился на поиски более естественных наборов чисел и функций, которые соответствовали бы унарным регулярным выражениям ECMAScript, возобновил совершенствование своего механизма регулярных выражений и также начал совершенствовать PCRE.

Я очарован чуждостью построения математических функций в регулярном выражении ECMAScript. К проблемам следует подходить с совершенно иной точки зрения, и до момента появления ключевого понимания неизвестно, решаются ли они вообще. Это заставляет создавать гораздо более широкую сеть, чтобы определить, какие математические свойства могут быть использованы для решения конкретной задачи.

Сопоставление факторных чисел было проблемой, которую я даже не рассматривал в 2014 году - или, если бы я сделал, только на мгновение, отклонил бы ее как слишком маловероятную, чтобы быть возможной. Но в прошлом месяце я понял, что это можно сделать.

Как и в других моих статьях по регулярным выражениям ECMA, я дам предупреждение: я настоятельно рекомендую научиться решать унарные математические задачи в регулярных выражениях ECMAScript. Для меня это было увлекательное путешествие, и я не хочу испортить его тем, кто потенциально может попробовать его сами, особенно тем, кто интересуется теорией чисел. См. Этот более ранний пост для списка последовательно рекомендованных спойлером рекомендованных проблем, чтобы решить одну за другой.

Так что не читайте дальше, если вы не хотите, чтобы какая-то продвинутая магия унарных регулярных выражений была испорчена для вас . Если вы действительно хотите сами разобраться в этой магии, я настоятельно рекомендую начать с решения некоторых проблем в регулярном выражении ECMAScript, как описано в этом посте, связанном выше.

Это была моя идея:

Проблема с сопоставлением этого набора номеров, как и с большинством других, заключается в том, что в ECMA обычно невозможно отслеживать два меняющихся числа в цикле. Иногда они могут быть мультиплексированы (например, полномочия одной и той же базы могут быть добавлены вместе однозначно), но это зависит от их свойств. Поэтому я не мог просто начать с входного числа и делить его на постепенно увеличивающиеся дивиденды, пока не достиг 1 (или я так думал, по крайней мере).

Затем я провел небольшое исследование множителей простых факторов в факторных числах и узнал, что для этого есть формула , которую я мог бы реализовать в регулярном выражении ECMA!

После того, как я немного поработал над этим и тем временем создал несколько других регулярных выражений, я решил написать факториальное регулярное выражение. Это заняло несколько часов, но в итоге все заработало. В качестве дополнительного бонуса алгоритм может возвращать обратный факториал как совпадение. Этого даже не избежать; по самой природе того, как это должно быть реализовано в ECMA, необходимо сделать предположение о том, что такое обратный факториал, прежде чем делать что-либо еще.

Недостатком было то, что этот алгоритм был создан для очень длинного регулярного выражения ... но я был рад, что в итоге ему потребовалась методика, используемая в моем регулярном выражении умножения 651 байт (которое оказалось устаревшим, потому что другой метод сделал для 50 байт регулярное выражение). Я надеялся, что возникнет проблема, требующая этого трюка: работа с двумя числами, которые являются степенями одной и той же базы, в цикле, путем однозначного их сложения и разделения на каждой итерации.

Но из-за сложности и длины этого алгоритма я использовал молекулярные взгляды (формы (?*...)) для его реализации. Это особенность не в ECMAScript или любом другом распространенном движке регулярных выражений, а та, которую я реализовал в своем движке . Без каких-либо захватов внутри молекулярного обзора он функционально эквивалентен атомному прогнозированию, но с захватами он может быть очень мощным. Движок вернется назад, и это может быть использовано для предположения значения, которое циклически перебирает все возможности (для последующего тестирования) без использования символов ввода. Их использование может сделать реализацию более чистой. (Внешний вид переменной длины по меньшей мере равен по мощности молекулярному взгляду, но последний имеет тенденцию создавать более прямые и элегантные реализации.)

Таким образом, длины в 733 и 690 байтов фактически не представляют ECMAScript-совместимые воплощения решения - отсюда и «+» после них; Конечно, возможно перенести этот алгоритм на чистый ECMAScript (который немного увеличит его длину), но я не смог обойти это ... потому что я подумал о гораздо более простом и более компактном алгоритме! Тот, который может быть легко реализован без молекулярных взглядов. Это также значительно быстрее.

Этот новый, как и предыдущий, должен угадать обратный факториал, перебирая все возможности и проверяя их на совпадение. Он делит N на 2, чтобы освободить место для работы, которую он должен выполнить, а затем запускает цикл, в котором он многократно делит входные данные на делитель, который начинается с 3 и увеличивается каждый раз. (Таким образом, 1! И 2! Не могут быть сопоставлены основным алгоритмом, и должны рассматриваться отдельно.) Делитель отслеживается путем добавления его к коэффициенту выполнения; эти два числа могут быть однозначно разделены, потому что, предполагая M! == N, текущий коэффициент будет делиться на M, пока он не станет равен M.

Это регулярное выражение выполняет деление на переменную во внутренней части цикла. Алгоритм деления такой же, как и в других моих регулярных выражениях (и похож на алгоритм умножения): для A≤B, A * B = C, если есть, только если C% A = 0 и B - наибольшее число, удовлетворяющее B≤C и C% B = 0 и (CB- (A-1))% (B-1) = 0, где C - дивиденд, A - делитель, а B - частное. (Аналогичный алгоритм может быть использован для случая, когда A≥B, и если неизвестно, как A сравнивается с B, все, что нужно, - это один дополнительный тест делимости).

Поэтому мне нравится, что эту проблему удалось снизить до еще меньшей сложности, чем мой регулярный код Фибоначчи, оптимизированный для гольфа , но я вздыхаю с разочарованием, что моей технике мультиплексирования «силы одного и того же основания» придется ждать еще одной проблемы это на самом деле требует этого, потому что это не так. Это история моего 651-байтового алгоритма умножения, замененного 50-байтовым, снова и снова!

Редактировать: мне удалось отбросить 1 байт (119 → 118) с помощью трюка, найденного Грими, который может дополнительно сократить деление в случае, когда коэффициент гарантированно будет больше или равен делителю.

Без дальнейших церемоний, вот регулярное выражение:

Верная / ложная версия (118 байт):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$|^xx?$

Попробуйте онлайн!

Возвращает обратный факториал или несоответствие (124 байта):

^(?=((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$)\3|^xx?$

Попробуйте онлайн!

Возврат обратного факториала или отсутствие совпадения в ECMAScript +\K (120 байт):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\K\3$|^xx?$

И свободная версия с комментариями:

  ^
  (?=                           # Remove this lookahead and the \3 following it, while
                                # preserving its contents unchanged, to get a 119 byte
                                # regex that only returns match / no-match.
    ((x*)x*)(?=\1$)             # Assert that tail is even; \1 = tail / 2;
                                # \2 = (conjectured N for which tail == N!)-3; tail = \1
    (?=(xxx\2)+$)               # \3 = \2+3 == N; Assert that tail is divisible by \3
    # The loop is seeded: X = \1; I = 3; tail = X + I-3
    (
      (?=\2\3*(x(?!\3)xx(x*)))  # \5 = I; \6 = I-3; Assert that \5 <= \3
      \6                        # tail = X
      (?=\5+$)                  # Assert that tail is divisible by \5
      (?=
        (                       # \7 = tail / \5
          (x*)                  # \8 = \7-1
          (?=\5(\8*$))          # \9 = tool for making tail = \5\8
          x
        )
        \7*$
      )
      x\9                       # Prepare the next iteration of the loop: X = \7; I += 1;
                                # tail = X + I-3
      (?=x\6\3+$)               # Assert that \7 is divisible by \3
    )*
    \2\3$
  )
  \3                            # Return N, the inverse factorial, as a match
|
  ^xx?$                         # Match 1 and 2, which the main algorithm can't handle

Полная история моих оптимизаций по гольфу этих регулярных выражений находится на github:

регулярное выражение для сопоставления факторных чисел - метод сравнения множественности, с молекулярным lookahead.txt
регулярное выражение для сопоставления факториальных чисел ( текст, показанный выше)

((x*)x*)((x*)+)((x+)+)Nзнак равно3!\23-3знак равно0

Механизм регулярных выражений .NET не эмулирует это поведение в режиме ECMAScript, и, таким образом, работает 117-байтовое регулярное выражение:

Попробуйте онлайн! (версия с экспоненциальным замедлением, с механизмом регулярных выражений .NET + эмуляция ECMAScript)


14

JavaScript (ES6), 30 29 28 байт

Ожидает положительное целое число. Возвращает -1за фальшивку и -2за правдивость.

f=(n,k=2)=>n>1?f(n/k,k+1):~n

console.log(1,  '-->',f(1))   // Truthy (0! or 1!)
console.log(2,  '-->',f(2))   // Truthy (2!)
console.log(3,  '-->',f(3))   // Falsey
console.log(4,  '-->',f(4))   // Falsey
console.log(5,  '-->',f(5))   // Falsey
console.log(6,  '-->',f(6))   // Truthy (3!)
console.log(7,  '-->',f(7))   // Falsey
console.log(8,  '-->',f(8))   // Falsey
console.log(24, '-->',f(24))  // Truthy (4!)
console.log(120,'-->',f(120)) // Truthy (5!)

Примечание : эта функция поддерживает довольно большие входные данные (вы должны прочитать это как «довольно большой для JS»). Он должен безопасно работать до 2 53 - 1 . Он наверняка потерпит неудачу, начиная с N = 121 645 100 408 831 992 , этот вход округляется до 19! = 121 645 100 408 832 000 из-за кодировки IEEE-754. Там могут быть и другие ложные положительные результаты до 121,645,100,408,831,991 из - за ошибок округления, но я не знаю точно.


Хорошо - очень нравится использование ~в конце.
Стив Беннет

Можете ли вы отредактировать, чтобы я мог отменить голосование? (Если вы хотите знать, почему я отказался от голосования, это потому, что я забыл о необычных правилах ввода-вывода в этом вопросе.)
CalculatorFeline

@ Arnauld Undownvoted.
CalculatorFeline

11

Python 3 , 39 38 байт

f=lambda n,i=1:n>1and f(n/i,i+1)or n<1

Рекурсивная функция , принимающая целое число, n, возвращая логическое значение , представляющее inversley результата (truthy: False, falsey: True)

Попробуйте онлайн!

Неоднократно делится nна i, с начальным значением 1, до тех пор, пока остаток не станет меньше или равен, а 1затем проверяет, будет ли этот остаток меньше 1, только факториалы будут заканчиваться остатком, равным 1, и< на байт короче, чем ==.


@ovs мы были ограничены двумя последовательными выходами. Это, к сожалению, возвращается 1для всех факториалов, за исключением 1которых оно возвращается True.
Джонатан Аллан

11

Java 8, 46 байт

i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;}

Это основано на записи Романа Грефа, с которой я смог выбить дюжину или около того байтов. Я бы предложил это там, но у меня пока недостаточно репутации, чтобы комментировать! Мой модифицированный код бегуна:

import java.util.function.Function;
import java.util.stream.IntStream;

public class IsFactorial {
    public static Function<Integer, Boolean> isFactorial = i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;};
    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};
    public static void main(String[] args){
        System.out.println(
            IntStream.of(truthyCases).allMatch(i->isFactorial.apply(i)) &&
            IntStream.of(falsyCases).allMatch(i->!isFactorial.apply(i)));
    }
}

9

Retina , 50 38 байт

12 байтов сохранены благодаря @Neil, объединяя сокращение цикла и избавляясь от ;

.+
1¶$&$*
+`^(1+)¶(\1)+$
1$1¶$#2$*
¶.$

Попробуйте онлайн!

Выходы 1для истины и0 ложного.

.+ соответствует всему числу

1¶$&$* заменив его 1 следующим символом перевода строки и соответствием

Оставшаяся программа делит унарное число в нижней строке путем последовательного увеличения натуральных чисел, отслеживая в верхней строке, в то время как это возможно.

+` цикл, пока строка не останется прежней

  • ^(1+)¶(\1)+$сопоставьте верхнюю строку многие 1s и кратные ей многие 1s в нижней строке и замените ее на

  • 1$1¶$#2$*в верхней строке много 1s с другим 1, то есть увеличивается число, представленное верхней строкой, на 1, за которым следует новая строка и количество совпадений верхней строки в нижней строке (т. е. количество совпадений второй группы захвата) ) многие 1s, то есть деление нижнего числа на верхнее число

Как только это уже невозможно сделать,

¶.$дать количество совпадений этого регулярного выражения, т.е. существует ли единица 1в нижней строке, что происходит, только если число является факториалом


Если вместо значений «истина / ложь» разрешено без сбоев / сбоев, тогда я могу получить 36 34 байта.

^
1¶
{`.+$
$*
^(1+)¶(\1)+$
1$1¶$#2

Это идет по тому же подходу, но объединяет $*в третью и четвертую строчки. Третья строка и далее является частью того же цикла, {сокращенно, +(где (группируются оставшиеся строки в цикле. Факториалы заканчиваются выходом программы из цикла, в то время как нефакториалы застревают в цикле до тех пор, пока Retina не сгенерирует исключение OverflowException, вызванное неудачной последней заменой, в результате чего дно будет в унарном, а не в десятичном виде, и в первой замене цикла преобразует нижнюю строку из десятичной в одинарную, поэтому она быстро взрывается.


Сохраните байт, удалив, 1как это подразумевается, когда $*в конце замены.
Нил

А еще лучше объединить $*две другие строки.
Нил


3
Я впечатлен, что вы нашли способ рухнуть Retina условно. :)
Мартин Эндер

2
Можете ли вы добавить объяснение?
CalculatorFeline

8

05AB1E , 4 байта

L!QO

Попробуйте онлайн!

объяснение

L      # range [1 ... input]
 !     # calculate factorial of each
  Q    # compare with input for equality
   O   # sum

1
Разве вам не нужно сначала дублировать ввод, потому что Lвыдает его ввод? Кроме того, Å!выдает список факториалов, меньших или равных входным данным.
Нил А.

@NeilA. К счастью, ввод снова появляется, если в стеке недостаточно аргументов для операции, поэтому мне Dздесь не нужно . Хорошо поймать Å!. Я всегда забываю о списке команд. Это не спасет ни одного байта, но наверняка будет более эффективным.
Эминья

Я не знал о том, что ввод вводится снова ... это наверняка может сэкономить много байтов.
Нил А.

@NeilA. Это довольно новая функция. Это было добавлено менее месяца назад, я думаю.
Эминья

8

C ++, 102 100 92 байта

#include<cmath>
int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}

Перебирает все значения от 0до nи вычисляет факториал, а затем проверяет, равно ли оно n.

Спасибо Кристоф! (сохранено 8 байт)


Здравствуй! Добро пожаловать в PPCG! Хороший первый ответ! Удачи в будущем!
Арджун

Хороший первый ответ! Вы можете сэкономить несколько байт , как это: int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}. lroundи lgammaуже C ++ 11, так что может просто #include<cmath>. Может быть, вы можете еще больше улучшить мои предложения :)
Кристоф

7

Haskell , 43 26 байтов

f n=elem n$scanl1(*)[1..n]

Попробуйте онлайн!

  • Сохранено 17 байтов, благодаря Laikoni

2
f n=elem n$scanl1(*)[1..n]смешно неэффективно, но короче.
Лайкони

Есть ли какое-то правило об эффективности кода?
sudee

1
Ни о чем я не знаю. code-golf запрашивает решение в минимально возможном количестве байтов без каких-либо заявлений об эффективности. Также на моей машине функция работает до40430 без заметной задержки.
Лайкони

Я имел в виду что-то вроде «решение должно завершиться в разумные сроки», но я думаю, что оно в любом случае соответствует требованиям. Благодарность!
sudee

1
Красиво и просто. Я думал, что смогу добиться большего успеха с делением, скажем, divModпо [1..]порядку, пока не достигну нулевого остатка с коэффициентом 1 (факториал) или ненулевым остатком (не факториал), но, похоже, это не правильный подход. Я нашел это симпатичное решение из 46 символов, хотя:f|let x%n=mod n x==0&&(x+1)%div n x||n==1=(1%) .
Джон Перди

6

Haskell , 38 байт

m#n=n<2||mod n m<1&&(m+1)#div n m
(2#)

Попробуйте онлайн! Пример использования: (2#) 24. Возвращает TrueилиFalse .

Это самое короткое, что я мог получить, оставаясь при этом очень эффективным. Даже для таких больших чисел, как

145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000

результат сразу дается. Решение работает путем деления входного nпути , m = 2,3,4,5,...пока либо результат не представляет собой один или nне делится наm .

Для более короткого, но невероятно неэффективного 26-байтового решения, которое вычисляет n! входные данные, которые не являются факториалами, смотрите здесь .



5

Фурье , 40 39 байт

I~Q1~N(i^~i*N~N{Q}{1~Xo}N>Q{1}{1~X0o}X)

Попробуйте это на FourIDE!

В основном умножает число N на увеличивающуюся величину до тех пор, пока N не станет равным (выход 1) или больше (выход 0) входа.

Пояснение псевдокод:

Q = Input
N = 1
While X != 1
    i += 1
    N = N*i
    If N = Q Then
        Print 1
        X = 1
    End If
    If N > Q Then
        Print 0
        X = 1
    End If
End While

5

Japt , 8 6 байт

ol x¥U

Попробуйте онлайн!

Это выводит 0 для false и 1 для true.

объяснение

 ol x¥ U
Uol x==U
Uo       # Create the range [0 ... input]
  l      # Replace each element by its factorial
     ==U # Compare each element to the input (yielding 1 if equal and 0 otherwise)
    x    # And sum the result

1
Я действительно должен добавить встроенное «содержит»: P
ETHproductions

1
О эй, вы могли бы изменить , aU ¦Jчтобы x¥U(сопоставьте каждый Xк X==Uи сумма), хотя это не будет работать на TIO.
ETHproductions

Неудачи, 2потому что oдаст только вам [0,1]. Вот исправление с сохранением 1 байта.
Лохматый

4

Perl 5, 31 байт

$a=<>;$a/=++$i while$a>1;exit$a

Ввод осуществляется через STDIN, выход - через код выхода (1 для факториала, 0 для нефакториала).

Входные данные делятся на последовательные целые числа до тех пор, пока они не станут равны 1 или некоторой доле меньше единицы, что усечено в результате.



4

Perl 6 , 29 байт

{($_,{$_/++$}...2>*).tail==1}

Попробуй это

Expanded:

{   # bare block lambda with implicit parameter 「$_」

  (              # generate a sequence

    $_,          # starting with the input

    {
      $_ / ++$   # divide previous element by an ever increasing number
                 # 1,2,3,4,5,6,7,8 ... *
    }

    ...          # keep generating until

    2 > *        # 2 is greater than what was generated
                 # ( 1 or a fractional number )

  ).tail == 1    # check if it ended at 1
}

17 байт: {$_∈[\*] 1..$_}. Еще один интересный подход 2>*.polymod(1..*).sum.
nwellnhof

4

setlX , 32 байта

f:=n|=>exists(x in{0..n}|n==x!);

Создает функцию под названием f которой вы используете свой потенциальный факториал в качестве параметра.

Это работает с произвольным целочисленным размером, но это довольно неэффективно.

(кстати: это мое первое участие в программировании)


4

C (gcc), 33 байта

e;f(n){n=n%++e?n==!(e=0):f(n/e);}

Обратите внимание, что некоторые авторы определяют «натуральное число» как положительное целое число. Поэтому мне все равно, что f(0)вызывает бесконечную рекурсию.



Может быть сброшен до 32 байтов: попробуйте онлайн! или 31 байт, возвращая ненулевое значение false: попробуйте онлайн!
Deadcode


4

C # (.NET Core) , 68 байт

bool f(System.Numerics.BigInteger n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

Попробуйте онлайн!

Не самое короткое решение, но работает с действительно большими числами. Ссылка TIO включает в себя пример с 10000!.

Вот более короткая версия, которая использует intмаксимальное значение 2147483647 .

C # (.NET Core) , 45 байт

bool f(int n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

Попробуйте онлайн!

Благодарим @KevinCruijssen за игру в гольф по 3 байта в обоих ответах!


2
&&Может быть golfed , чтобы &и тянущийся ;не должен учитываться для функций лямбды. Кроме того, не может ulong k=2быть uint k=2в вашем 50-байтовом ответе?
Кевин Круйссен

1
Хороший улов &против &&. Я думал, что получаю переполнение стека, но это, кажется, работает в конце концов. ulong64 бит, а uint32. Похоже, что другие используют, intтак что, возможно, я просто буду использовать это для короткой версии. Что касается трейлинга ;, это полные функции, а не лямбды, так что я думаю, что мне нужно их включить?
Дана

Это действительно странно, как .NET может разрешать /и %между ulongиuint , но не ulongи int. Не знал этого :)
Дана

1
@Oliver - Когда doubleвы начинаете видеть округление в какой-то момент - например, 24! и 120! провал. Хотя System.Numerics.BigIntegerимеет большую точность,int это самый короткий ответ :)
Дана

1
@Deadcode - Вы правы насчет 0 :) Основываясь на примерах в задании, я интерпретировал "натуральные числа" как 1,2 ... Я согласен, что в реальном мире лучше использовать &&оператор короткого замыкания , Но это код гольфа;) Рад, что вам нравится 10000!пример!
Дана

4

C ++ (лязг), 51 байт

Рекурсия выигрывает, если играть в гольф.

51 байт, ноль - это правда:

int f(int n,int i=2){return n<2?!n:n%i|f(n/i,i+1);}

Это жертвует довольно большой скоростью за 1 байт экономии. Заменить |с , ||чтобы сделать это быстро, из - за оценки короткого замыкания логического ИЛИ.

Попробуйте онлайн! (Медленная версия 51 байт)
Попробуйте онлайн! (52 байт, быстрая версия)

Ungolfed медленная версия:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    // Because any nonzero value represents "false", using "|" here is equivalent
    // to "||", provided that the chain of recursion always eventually ends. And
    // it does always end, because whether or not "n" is factorial, the "n / i"
    // repeated division will eventually give the value of zero or one, satisfying
    // the above condition of termination.
    return (n % i) | isFactorial(n / i, i+1);
}

Ungolfed быстрая версия:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    if (n % i != 0)
        return 1; // not factorial
    else
        return isFactorial(n / i, i+1);
}

Есть много способов изменить это.

52 байта, ненулевое значение true:

int f(int n,int i=2){return n<2?n:n%i?0:f(n/i,i+1);}

Попробуйте онлайн!

52 байта, ноль - это правда:

int f(int n,int i=2){return!n?1:n%i?n-1:f(n/i,i+1);}

Попробуйте онлайн!

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

54 байта, ненулевое значение true:

int f(int n){for(int i=2;n>1;)n=n%i?0:n/i++;return n;}

Попробуйте онлайн!

54 байта, ноль - истина (основано на представлении Романа Грефа Java 8 ):

int f(int n){int a=1,i=0;for(;a<n;a*=++i);return a-n;}

Попробуйте онлайн!

Теперь, для дна ствола, рекурсивные версии без n==0обработки (я считаю их недействительными, потому что 0 - натуральное число, и любое определение, в котором оно не используется, для «натуральных чисел» очень ограниченного использования). В следующих версиях бесконечная рекурсияf(0) запускает segfault из-за переполнения стека, или с помощью компиляторов, которые оптимизируют его для итерации, зацикливается бесконечно:

48 байтов, ноль - это правда:

int f(int n,int i=2){return n%i?n-1:f(n/i,i+1);}

Попробуйте онлайн!

48 байтов, ноль - истина (на основе 33-байтового представления Хагена фон Эйтцена C (gcc) ):

int f(int n,int e=0){return n%++e?n-1:f(n/e,e);}

Попробуйте онлайн!


50 РЕДАКТИРОВАТЬ: 49 , без рекурсии.
Grimmy

Вернуться к рекурсии за 48 . И вам, вероятно, это не понравится, но 44 с использованием глобальной переменной.
Grimmy

3

Mathematica, 20 байтов

!FreeQ[Range[#]!,#]&

другая версия для проверки больших чисел (см. комментарии)

Range[10^3]!~MemberQ~#&

тесты до 1000!


2
Насколько я понимаю вопрос, способен ли Mathematica брать 1001! в качестве входа, то это не соответствует спецификации.
Питер Тейлор

2
Вы даже можете сохранить три байта, делая его действительным для всех входных данных. Просто замените 10 ^ 3 на #; Вы можете сохранить еще один байт с помощью Range @ #
Julien Kluge

@Julien Klugethen поиск 1243234 занял бы вечно ...
J42161217

1
Я думаю, что вы можете сохранить другой байт, заменив Range[#]на Range@#:)
numbermaniac

3
Похоже , вы можете сохранить еще один байт с синтаксисом инфиксной: !Range@#!~FreeQ~#&.
Numbermaniac

3

Cubix , 24 байта

U0O@1I1>-?1u>*w;W;@Orq)p

Попробуйте онлайн

Cubified

    U 0
    O @
1 I 1 > - ? 1 u
> * w ; W ; @ O
    r q
    ) p

Начнем с нажатия 1, Input,1 на стек. Это будет наш индекс, наша цель и наш аккумулятор, соответственно.

Затем мы зациклимся. На каждой итерации мы вычитаем аккумулятор из входных данных. Если результат равен 0, мы закончили, поэтому мы нажимаем 1, выполняем и завершаем работу O. Если оно отрицательное, мы зашли слишком далеко, поэтому мы нажимаем 0, Oвыводим и выходим. В противном случае мы видим

;p)*rq;
;         Pop the difference off the stack.
 p)       Move the index to the top of the stack and increment it.
   *      Multiply the accumulator by the index to get the next factorial.
    rq;   Put the stack back in the right order.

3

Нейм , 8 байт

𝐈Γ𝐈𝐩₁𝔼)𝐠

Объяснение:

Example input: 6
𝐈         Inclusive range [1 .. input]
          [1, 2, 3, 4, 5, 6]
 Γ        For each...
  𝐈         Inclusive range [1 .. element]
            [[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6]]
   𝐩        Product
            [1, 2, 6, 24, 120, 720]
     𝔼      Check for equality with
    ₁       the first line of input
            [[0, 0, 1, 0, 0, 0]]
      )   End for each
       𝐠  Select largest element
          [1]

Попытайся!

Neim , 3 байта (не конкурирует)

Неконкурентные, так как токен содержимого и факториальный токен были добавлены после вызова.

𝐈𝐓𝕚

Объяснение:

Example input: 6
𝐈     Inclusive range [1 .. input]
      [[1, 2, 3, 4, 5, 6]
 𝐓    Factorial each
      [[1, 2, 6, 24, 120, 720]]
  𝕚   Check that the [cycled] input is in the list
      [1]

Попытайся!


3

> <> , 24 22 байта

-2 байта благодаря @ Аарону

Я пробую новый язык (так как моя лицензия на Mathematica истекла ...)

01\{=n;
?!\$1+:@*:{:}(

Попробуйте онлайн или на рыбной площадке

Предполагается, что входной номер уже находится в стеке и возвращает 0 или 1. Он работает, умножая вместе первые n чисел до тех пор, пока они не перестанут быть меньше, чем ввод, а затем печати 1, если он равен входу, и 0, если он не ' т.


Вы можете превратить вас v>\n<^в \\n/; смотрите здесь
Аарон

@ Аарон, это замечательно, спасибо!
Не дерево

3

APL (Dyalog Unicode) , 5 6 7 байт

Golfed байт путем изменения ×/в !благодаря Эрику Outgolfer

⊢∊!∘⍳

Попробуйте онлайн!

объяснение

                          Range of numbers from 1 to argument, 1 2 3 4 .. n
   !                       Factorial; 1! 2! 3! 4! .. n!
⊢∊                         Is the right argument a member of this list?

Накопительная сумма?
Утренняя монахиня

@LeakyNun Исправлено
Kritixi Lithos

Один дополнительный байт в GNU APL 1.2. N∊×\⍳N←⎕Как это принять аргумент? Я nнигде не вижу . Это специфичная для Dyalog вещь?
Arc676

2
@ Arc676 Мое решение - поезд, и вы называете его так: (⊢∊(×/⍳)) right_argumentкак вы видите по ссылке TIO. И относится к правильному аргументу.
Критиси Литос

Примечания: AGL сэкономит вам байт; ⊢∊×\ä⍳, «Правильное» (но более длинное) решение было бы 0=1|!⍣¯1; "Является ли обратный факториал целым числом?"
Адам

2

JavaScript (ES6), 71 байт

Это принимает входные данные в качестве аргумента функции и alertвыводит их. Выходы 0для фальси и 1правды.

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}alert(r)}

объяснение

Программа состоит из двух функций fиg . fявляется рекурсивной факториально-вычислительной функцией и gявляется основной функцией программы. g предполагает наличие единственного аргумента n. Он определяет аргумент по умолчанию rсо значением 0 и другой аргумент по умолчанию со значением 0. Затем он перебирает все целые числа от 0 до nи на каждой итерации проверяет, равна ли функция, fпримененная над i(текущий индекс) n, т. Е. nЯвляется ли факториал из i. Если это случается так, rзначение «s устанавливается равным 1. В конце функции, rявляетсяalert ред.

Тестовый фрагмент

( Примечание . Фрагменты выводятся с использованием, console.log()как никто не любит слишком много этих надоедливых alert()s. )

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}console.log(r)}

g(1)
g(2)
g(3)
g(4)
g(5)
g(6)
g(7)
g(8)
g(24)
g(120)


Eval может быть короче, чем использование блока кода.
Downgoat

@ Downgoat Как мне это сделать? Извините, если это слишком очевидно! : P
Арджун

2

QBIC , 21 19 байтов

[:|q=q*a~q=b|_x1}?0

объяснение

[:|     Start a FOR loop from 1 to n
q=q*a   q starts as 1 and is multiplied by the FOR loop counter
        consecutively: q=1*1, *2, *3, *4 ... *n
~q=b|   If that product equals n
_x1     Then quit, printing a 1
}       Close the IF and the FOR
?0      If we're here, we didn't quit early and didn't find a factorial, print 0

предварительно

[:|q=q*a┘c=c+(q=b)}?c

Объяснение:

[:|         Start a FOR loop from 1 to n
q=q*a       q starts as 1 and is multiplied by the FOR loop counter
            consecutively: q=1*1, *2, *3, *4 ... *n
┘           Syntactic line break
c=c+        c starts out at 0 and then keeps track of 
    (q=b)       how often our running total == n
}           Closes the FOR-loop
?c          Print c, which is 0 fir non-factorials and -1 otherwise.

2

Java 8, 59 байт

i->{for(int j=1,c=0;j<=i;j*=++c)if(j==i)return 1;return 0;}

Testcode

import java.util.function.IntFunction;
import java.util.stream.IntStream;

public class IsFactorial
{
    public static IntFunction<Integer> isFactorial = i->
    {
        for(int j=1,c=0;j<=i;j*=++c)
            if(j==i)return 1;return 0;
    };

    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};

    public static void main(String[] args)
    {
        System.out.println
        (
            IntStream.of(truthyCases)
                .allMatch(i->isFactorial.apply(i)==1)
            && IntStream.of(falsyCases)
                .allMatch(i->isFactorial.apply(i)==0)
        );
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.