40
\$\begingroup\$

The Task

Given a natural number as input, your task is to output a truthy or falsey value based on whether the input is a factorial of any natural number. You can assume that the input number will always be in the range of numbers supported by your language, but you must not abuse native number types to trivialize the problem.

Standard Loopholes apply.


Input

You'll be given a natural number (of type Integer or similar).

You can take input in any way you want except assuming it to be in a predefined variable. Reading from file, console, dialog box (prompt), input box etc. is allowed. Input as function argument is allowed as well!


Output

Your program should output a truthy or falsey value based on whether the input number is a factorial of any natural number.

Make sure that your truthy/falsey values are consistent for all inputs, i.e, if you are using pair of 1 and 0 to denote truthy and falsey values respectively, then your program must output 1 for all inputs that should have truthy values and 0 for all inputs that should have falsey values.

You can take output in any way you want except writing it to a variable. Writing to file, console, screen etc. is allowed. Function return is allowed as well!

Your program must not produce errors for any input!


Test Cases

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!)

Winning Criterion

This is , so the shortest code in bytes wins!

\$\endgroup\$
4
  • 2
    \$\begingroup\$ If the language supports only numbers in the range {0,1}, can I expect the input to always be 1? \$\endgroup\$ – eush77 May 20 '17 at 9:45
  • 11
    \$\begingroup\$ @eush77 Abusing native number types to trivialize a problem is forbidden by default. \$\endgroup\$ – Dennis May 20 '17 at 17:56
  • 1
    \$\begingroup\$ is 4! a truthy? \$\endgroup\$ – tuskiomi May 20 '17 at 22:04
  • \$\begingroup\$ Question: Why aren't you using the I/O defaults? \$\endgroup\$ – CalculatorFeline May 22 '17 at 23:15

84 Answers 84

1 2
3
1
\$\begingroup\$

Brain-Flak, 154 bytes

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

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Alchemist, 265 264 bytes

_->a+In_b+q
q+b->q+h+c
q+0b->r
r+h->r+b
r+0h->s
s+i->s+j+m
s+0i->t
t+a->t+d
t+0a->u
u+d->u+a+n
u+0d->v
v+n->v+h
v+0n+m->t
v+0n+0m->p
p+a->p
p+0a->w
w+h->w+a+f
w+j->w+i
w+0j+0h->i+x
x+b+f->x
x+0b+0f->Out_"1"
x+0b+f->Out_"0"
x+b+0f->y
y+b->y
y+0b->z
z+c->z+b
z+0c->q

Outputs 1 if it's a factorial and 0 otherwise: Try it online or test the first n factorials!

Ungolfed

The non-determinism comes from the rules

w+h->w+a+f     # s6 +  tmp -> s6 + accum + factorial
w+j->w+i       # s6 + counter_copy -> s6 + counter
w+0j+0h->i+x   # s6 + 0counter_copy + 0tmp -> counter + s7

which could be serialised to

w+h->w+a+f   # s6 +  tmp -> s6 + accum + factorial
w+0h->o      # s6 + 0tmp -> _s6
o+j->o+i     # _s6 +  counter_copy -> _s6 + counter
o+0j->i+x    # _s6 + 0counter_copy -> counter + s7

such that the tmp-atom will be duplicated first and only then counter_copy renamed to counter and incremented:

Try it online! (see debugging output)

But it should be clear that this non-determinism will not change the result of the complete computation:

# initialize accumulator & read input
_ -> accum + In_input + s0

# duplicate the input
s0 +  input -> s0 + tmp + input_copy
s0 + 0input -> s1

s1 +  tmp -> s1 + input
s1 + 0tmp -> s2

# duplicate the counter
s2 +  counter -> s2 + counter_copy + multiplier
s2 + 0counter -> s3

# duplicate the accumulator: factor <- accum
s3 +  accum -> s3 + dup
s3 + 0accum -> s4

s4 +  dup -> s4 + accum + factor
s4 + 0dup -> s5

s5 + 0factor +  multiplier -> s3   # while multiplier > 0:
s5 +  factor -> s5 + tmp           #   add factor: tmp += factor

# when "loop" is done, cleanup accum and continue
s5 + 0factor + 0multiplier +  accum -> s5
s5 + 0factor + 0multiplier + 0accum -> s6

# tmp holds the next factorial, keep it (non-deterministic)
s6 +  tmp -> s6 + accum + factorial
# restore counter

# restore counter and increment it
s6 + counter_copy -> s6 + counter
s6 + 0counter_copy + 0tmp -> counter + s7

# compare current factorial and input
s7 +  input +  factorial -> s7
s7 + 0input + 0factorial -> Out_"1"  # if factorial == input: done (success)
s7 + 0input +  factorial -> Out_"0"  # elif factorial > input: done (current factorial exceeds input)
s7 +  input + 0factorial -> s8       # input > factorial: try next factorial

# cleanup from before
s8 +  input -> s8
s8 + 0input -> s9

# restore input and continue
s9 +  input_copy -> s9 + input
s9 + 0input_copy -> s0

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ 159 \$\endgroup\$ – ASCII-only Jan 30 '19 at 7:23
1
\$\begingroup\$

Julia 1.0, 26 bytes

x->x in Base._fact_table64

Factorial is implemented as a lookup table in Julia, so lets just see if our value is in the table. Accurate for Int64, would be wrong for factorials that require a larger Integer type to represent.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C, 50 bytes

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

Special Thanks to Jo King for shortening the program.

\$\endgroup\$
2
  • \$\begingroup\$ Ah, you can also combine the p and i initialisations to remove a byte \$\endgroup\$ – Jo King Aug 6 '19 at 4:11
  • \$\begingroup\$ Building on @JoKing 44 bytes \$\endgroup\$ – ceilingcat Sep 27 '19 at 17:53
1
\$\begingroup\$

TI-BASIC, 13 bytes

sum(Ans=seq(X!,X,1,69

Input is an integer in Ans.
Output is 1 if the input is a factorial, 0 if not.

Due to precision in = checks being limited to 10 decimal places, this program will produce erroneous answers for numbers whose length is \$>10\$ digits.

Explanation:

        seq(X!,X,1,69  ;generate a list of all factorial numbers that
                       ;  TI-BASIC can store
    Ans=               ;equality check of the input against all members,
                       ;  1 if true, 0 if false
sum(                   ;sum the elements in the list
                       ;leave the result in Ans
                       ;implicit print of Ans

Examples:

720:prgmCDGF27
               1
25:prgmCDGF27
               0

Note: TI-BASIC is a tokenized language. Character count does not equal byte count.

\$\endgroup\$
1
\$\begingroup\$

Python 3.8 (pre-release), 47 bytes

lambda n,t=1:n in[t:=t*i for i in range(1,n+1)]

Try it online! This is not a Python winner, but it does showcase the walrus operator := in a scenario that isn't the typical look at me I'm golfing this and writing really obfuscated Python code :)

\$\endgroup\$
1
\$\begingroup\$

cQuents, 3 bytes

?$!

Try it online!

As I said in another question, cQuents is made for this.

?   # Query (Outputs if in the sequence)
 $! # Factorial
\$\endgroup\$
0
\$\begingroup\$

Perl 6, 17 bytes

{$_∈[\*] 1..$_}

Checks whether $_, the argument, is a member of the triangular multiplication reduction (1, 1*2, ..., 1*2*...*$_).

This does a LOT of unnecessary math for larger inputs, but hey, it's short!

\$\endgroup\$
0
\$\begingroup\$

Axiom, 67 bytes

f(x:NNI):Boolean==(i:=2;r:=1;repeat(r>=x=>break;r:=r*i;i:=i+1);r=x)

some test

(12) -> [[i,f(i)] for i in [0,1,2,3,6,24,25,120,720]]
   (12)
   [[0,false], [1,true], [2,true], [3,false], [6,true], [24,true], [25,false],
    [120,true], [720,true]]
                                                      Type: List List Any
\$\endgroup\$
0
\$\begingroup\$

2Col, 5 bytes [non-competing]

F!
$^

Try it in 2CollIDE

Basically the same as the Jelly answers. Link leads to the current 2Col interpreter in TIO, with the above code already inserted. 3rd argument is input.

2Col is a language where each line is a 2 character expression of some form. It's what I like to call an "Accumulator-based" language. It works like Stack-based languages, except the "stack" can only contain a single item.

Explanation:

      Implicit input to Cell
F!    Return [1!, 2!, ... n!]
$^    Return whether above return value contains Cell value
      Implicit: Print final line's return value
\$\endgroup\$
0
\$\begingroup\$

Tcl, 71 bytes

incr p
while \$p<$argv {set p [expr $p*[incr i]]}
puts [expr $p==$argv]

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Note: $argv is the variable that carries the argument from console; I had just overridden it to test all test cases at once! \$\endgroup\$ – sergiol Sep 23 '17 at 1:45
0
\$\begingroup\$

Tcl, 69 bytes

proc F n {incr p
while \$p<$n {set p [expr $p*[incr i]]}
expr $p==$n}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Now as a function it renders 2 bytes less! \$\endgroup\$ – sergiol Sep 23 '17 at 1:57
0
\$\begingroup\$

Zephyr, 86 bytes

input n as Integer
set i to 1
set f to 1
while f<n
inc i
set f to f*i
repeat
print f=n

Try it online!

f successively takes the value of every factorial from 1 on up, until it is no longer less than the input number n. If f is now equal to n, then n is a factorial and we output true; otherwise, n is not a factorial and we output false.

\$\endgroup\$
0
\$\begingroup\$

JavaScript, 124 bytes

I am nub so here it is:

a=(i)=>{r=1;n=0;while(n>=0){n++;r=r*n;if(i==r){console.log(i,"truthy:",n+"!");break;}else{console.log(i,"falsey:",n+"!");}}}

This link may or may not work. If it does, click run and then type "a(24)" or "a(120)" etc. If you pass-in a non-factorial int, it will run infinitely... so don't do that.

\$\endgroup\$
1
  • \$\begingroup\$ Output is allowed as return values, which could save you a lot of bytes. \$\endgroup\$ – Nissa May 18 '18 at 16:26
0
\$\begingroup\$

Forth (gforth), 58 bytes

Surprisingly, the shortest method I could find to do this was iterating the factorial numbers and comparing them to the input.

: f >r 1 1 begin 1+ tuck 1- * tuck r@ >= until r> nip = ; 

Try it online!

Explanation

>r              \ place the input on the return stack (saves a lot of stack operations)
1 1             \ place the current factorial-value and the index on the stack
begin           \ start an indefinite loop
   1+ tuck 1-   \ increment the index, save a copy, and then decrement again
   * tuck       \ multiply the factorial and the index and save a copy
   r@           \ copy the input from the return stack
   0>=          \ check if it's greater than or equal to the factorial-value
until           \ end the indefinite loop
r> nip          \ move the input back to the normal stack and delete the index
=               \ compare the input and the final factorial value
\$\endgroup\$
0
\$\begingroup\$

Python 3, 92 bytes

f=lambda n,i='1':n<2or(eval(i)==n if eval(i)>=n else f(n,i+'*%d'%(int(i.split('*')[-1])+1)))

Try it online!

This is the first thing I thought of seeing this challenge, but it didn't turn out as well as I had it in my head, easily beaten by other solutions.

Thanks to lambda for noticing a bug in my submission.

\$\endgroup\$
1
  • \$\begingroup\$ Is there a point to using strings and then evaling it instead of just using a separate variable to keep track of the number? e.g. 46 bytes \$\endgroup\$ – Jo King Jan 22 '19 at 5:30
0
\$\begingroup\$

CJam, 10 bytes

q~_),:m!&,

Try it online!

Uses similar logic as @FrodCube, but instead calculates set intersection and gets the length of the input. If the last , is dropped, you still get truthy/falsy values, but they are not consistent.

\$\endgroup\$
0
\$\begingroup\$

C#, 43 40 bytes, 41 bytes fallback

Uses a for loop to increment a number to divide the input by until the variable containing the input is no longer more than one. Returns false if the input is a factorial, true otherwise. The expression type is Func<dynamic, System.Func<dynamic, bool>> and it can take the same input for both calls. In case that isn't allowed, the fallback answer is System.Func<dynamic, bool>.

Short Answer

Try it online!

m=>s=>{for(s=2f;m>1;)m/=s++;return m<1;}

Fallback

Try it online!

m=>{for(var s=2f;m>1;)m/=s++;return m<1;}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I unfortunately think this solution is incorrect. Perhaps there was some confusion regarding integer division? Here is a link to some failing test cases: Try it online! \$\endgroup\$ – dana Jan 22 '19 at 13:30
  • \$\begingroup\$ @dana you're right, I didn't account for m/s being between 1 and 2 and ending up 1 for a non-factorial. \$\endgroup\$ – Ceshion Feb 19 '19 at 15:08
0
\$\begingroup\$

Tidy, 18 bytes

{x:x in(!)on[1,x]}

Try it online!

Simply tests if x is in the list generated by taking the factorial of each element in [1, x].

\$\endgroup\$
0
\$\begingroup\$

GolfScript, 17 bytes

~.),{,1\{)*}/}%?)

Try it online!

Explanation

~                  # Evaluate the input
 .                 # Duplicate the value
  )                # Increment the value
   ,               # Generate range from 1 to input
    {        }%    # Map every item
     ,             # Generate a to-0 range
      1\           # Make the initial product 1
        {  }/      # Foreach over the product:
         )*        # Multiply by the value incremented by 1
               ?)  # Index, and then logicize it
\$\endgroup\$
0
\$\begingroup\$

Burlesque, 13 bytes

riJro?!jFi0>=

Try it online!

If you accept -1 as falsey (technically isn't in burlesque) and >0 as truthy can save 3 bytes.

riJ # Read as int and duplicate on stack
ro  # Range from [1,N]
?!  # Factorial each
jFi # Find the index of the element == N
0>= # Found index
\$\endgroup\$
0
\$\begingroup\$

Fortran (GFortran), 57 bytes

read*,i
k=1
do j=1,i
k=k*j
if(i==k)l=1
enddo
print*,l
end

Try it online!

On some compilers may result in gibberish on false-y due to uninitialised l. Can be solved with 3 bytes (l=0) or compiler flags (e.g. -finit-integer=0). Strictly 1 is not a truthy in Fortran, but spec specified 1/0 for true/false.

\$\endgroup\$
0
\$\begingroup\$

Add++, 10 bytes

L,R€R€b*Ae

Try it online!

How it works

L,		; Define the main function that takes one argument, x
		; Example: x = 24		STACK = [24]
	R	; Range				STACK = [[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]]
	€R	; Range for each		STACK = [[[1] [1 2] [1 2 3] ... [1 2 3 ... 22 23 24]]
	€b*Bh	; Product for each		STACK = [[1 2 6 ... 620448401733239439360000]]
	Ae	; Is x in the array?		Returns 1
\$\endgroup\$
0
\$\begingroup\$

ink, 52 bytes

=t(n)
~temp f=1
-(l){n<f:{n==1}->->}
~n=n/f
~f++
->l

Try it online!

Assumes the input is a floating point number. If the number is integer-type, the division on line 4 truncates the quotient, which can cause false positives.
Prints its output (1 or 0) directly to stdout. Because ink.

Ungolfed

== check_if_factorial(input) ==
~ temp iterator = 1
- (loop)
{
    - iterator < input:
        {n == 1 : 1 | 0}
        ->->
}
~ input = input / iterator
~ iterator++
-> loop
\$\endgroup\$
1 2
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.