Чи є це число факторіальним?


38

Завдання

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

Застосовуються стандартні лазівки .


Вхідні дані

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

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


Вихідні дані

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

Переконайтесь, що ваші значення truthy / falsey відповідають усім вхідним даним, тобто, якщо ви використовуєте пари 1 і 0 для позначення значень truthy та falsey відповідно, ваша програма повинна виводити 1 для всіх входів, які повинні мати значення truthy та 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! правда?
тускіомі

Питання: Чому ви не використовуєте параметри вводу / виводу за замовчуванням?
CalculatorFeline

Відповіді:


37

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

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

Пояснення

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


6
@BetaDecay Це тому, що це надруковано в Prolog (це пов'язано з тим, що true.це твердження, а trueні)
Fatalize

6
Це банальне рішення, але розумне через те, як працює пролог.
Esolanging Fruit


17
Спочатку спеціальні мови, потім спеціальні кодування ... гольф коду мертвий. Ми повністю перекрутили всю точку цих веселих проблем в першу чергу
Олександр

13
@Alexander Спеціальні кодування не стосуються будь-якої проблеми, про яку ви говорите. Я міг би використати будь-яке "існуюче" кодування замість цього, і все одно це буде 1 байт. Це було б набагато менш читабельно.
Фаталізувати


19

Желе , 4 байти

Œ?IE

Не найкоротша відповідь Желе, але це досить ефективно.

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

Як це працює

Œ?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
Це кардинальне поліпшення складності за рахунок одного байта, і це розумне використання вбудованого, якщо я можу так сказати сам. ¯ \ _ (ツ) _ / ¯
Денніс

Цікаво, що це повертає значення "0", тоді як @ LeakyNun 3-байтний варіант відповіді, хоча набагато повільніше загалом, правильно повертає помилку на 0. Чи потрібні додаткові байти, щоб повернути помилкове значення 0 у відповідь на час ефективного виконання?
Deadcode

@Deadcode Для перевірки 0 потрібно два додаткові байти. Якщо не впевнено, чи містить ОП визначення "натуральних чисел" 0 чи ні. Тестові справи не ...
Денніс

17

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

Мій інтерес до регексу був викликаний новою силою після більш ніж 4½ років бездіяльності. Таким чином, я пішов шукати більш природні набори чисел та функції, які б відповідали одинарним регулярним виразам ECMAScript, відновив вдосконалення моєї системи регексу, а також почав чистити на PCRE.

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

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

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

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

Така моя ідея:

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

Тоді я провів кілька досліджень щодо множинності простих факторів у фактичних числах і дізнався, що для цього є формула - і це, можливо, я міг би реалізувати в регулярному виразі ECMA!

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

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

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

Отже, довжина 733 та 690 байт насправді не представляє сумісні з ECMAScript втілення рішення - отже, "+" після них; це, безумовно, можливо, щоб перенести цей алгоритм до чистого ECMAScript (що би збільшило його довжину зовсім небагато), але я не обійшов його ... тому що я думав про набагато простіший і компактніший алгоритм! Той, який можна було б легко реалізувати без молекулярних лукаголов. Це також значно швидше.

Цей новий, як і попередній, повинен здогадуватися на зворотному факторіалі, перебираючи всі можливості та перевіряючи їх на відповідність. Він ділить N на 2, щоб звільнити роботу, яку йому потрібно виконати, а потім наділяє цикл, в якому він буде неодноразово ділити вхід дільником, що починається на 3 та з кроком щоразу. (Таким чином, 1! І 2! Не можуть бути узгоджені з основним алгоритмом, і їх слід вирішувати окремо.) Дільник відстежується, додаючи його до діючого коефіцієнта; ці два числа можна однозначно розділити, оскільки, припускаючи М! == 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:

регулярний вирівнювання для збігу фактичних чисел - метод порівняння кратності, з молекулярним reox
lookahead.txt для відповідності фактичних чисел.txt (показаний вище)

((x*)x*)((x*)+)((x+)+)н=3!\23-3=0

Режим двигуна .NET не імітує цю поведінку в режимі ECMAScript, і, таким чином, 117-байтний регулярний вираз працює:

Спробуйте в Інтернеті! (версія експоненціального сповільнення, з двигуном .ge regex + емуляція 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 Скасовано.
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

Сітківка , 50 38 байт

12 байт збережено завдяки @Neil, поєднуючи скорочення циклу та позбавлення від ;

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

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

Виходи 1для істинних та0 для помилкових.

.+ відповідає всій кількості

1¶$&$*замінивши його з 1наступним новим рядком, і відповідність перетвориться на одинакову

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

+` цикл, поки рядок не залишиться однаковим

  • ^(1+)¶(\1)+$збігайте верхню лінію 1з множиною s, а кратну - з кількома 1s на нижній лінії та замініть на

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

Як тільки це вже не можливо зробити,

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


Якщо без краху / краху дозволено замість значень truthy / falesy, я можу отримати 36 34 байт.

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

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


Збережіть байт, видаливши 1як він мається на увазі $*в кінці заміни.
Ніл

А ще краще поєднати $*два інші рядки.
Ніл


3
Мені вражено, що ви знайшли спосіб умовно розбити сітківку. :)
Мартін Ендер

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]

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


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 для хибних та 1 для істинних.

Пояснення

 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 байт.
Shaggy

4

Perl 5, 31 байт

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

Введення приймається через STDIN, вихід - через вихідний код (1 для факторних, 0 для нефакторних).

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


-5 байт TIO
Nahuel Fouilleul

4

Perl 6 , 29 байт

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

Перевірте це

Розширено:

{   # 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 байт, повернувши нулеве значення для помилкового: Спробуйте в Інтернеті!
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
Хороший улов на &проти &&. Я думав, що я отримую переповнення стека, але, здається, це працює задовго. ulongце 64 біт, а 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 байт швидка версія)

Нескорочена повільна версія:

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);
}

Незабудована швидка версія:

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 байти, ненульове значення має місце:

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 байти, ненульове значення відповідає дійсності:

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)або запускає сегмент за замовчуванням через переповнення стека, або компілятори, які оптимізують його до ітерації, безперервно циклуються:

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 EDIT: 49 , без рекурсії.
Grimmy

Назад до рекурсії протягом 48 років . І вам, мабуть, це не сподобається, але 44 , використовуючи глобальний var.
Гріммі

3

Математика, 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

Кубікс , 24 байти

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

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

Кубіфікований

    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]

Спробуй це!

Нейм , 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 байти завдяки @Aaron

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

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

Спробуйте в Інтернеті або на рибному майданчику

Припустимо, що вхідне число вже є в стеку , і повертає 0 або 1. Він працює, множивши разом перші n числа, поки це не перестане бути меншим за вхід, а потім надрукує 1, якщо воно дорівнює вводу, і 0, якщо він не ' т.


Ви могли перетворити вас v>\n<^на \\n/; дивіться тут
Аарон

@Aaron, це геніально, дякую!
Не дерево

3

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

Отримав байт, змінивши ×/його !завдяки Еріку Атгольферу

⊢∊!∘⍳

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

Пояснення

                          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ніде не бачу . Це специфічна для Діалога річ?
Arc676

2
@ Arc676 Моє рішення - поїзд, і ти називаєш його так: (⊢∊(×/⍳)) right_argumentяк ви бачите за посиланням TIO. І посилається на правильний аргумент.
Kritixi Lithos

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

2

JavaScript (ES6), 71 байт

Це приймає введення як аргумент функції та alerts вихід. Виходи 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значення встановлюється на 1. В кінці функції, rєalert ред.

Тест-фрагмент

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

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 Як мені це зробити? Вибачте, якщо це занадто очевидно! : 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;}

Тестовий код

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.