57
\$\begingroup\$

Task

Given a non-negative integer \$n\$, evaluate the factorial \$n!\$.

The factorial is defined as follows:

$$ n!=\begin{cases}1 & n=0\\n\times(n-1)!&n>0\end{cases} $$

Rules

  • All default I/O methods are allowed.
  • Standard loopholes are forbidden.
  • Built-ins are allowed.
  • There is no time or memory limit.
  • Giving imprecise or incorrect results for large inputs due to the limit of the native number format is fine, as long as the underlying algorithm is correct. Specifically, it is not allowed to abuse the native number type to trivialize the challenge, which is one of the standard loopholes.
  • This is . Shortest code in bytes wins, but feel free to participate in various esolangs (especially the ones hindered by the restrictions of the former challenge).

Test cases

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600

Note: We already have the old factorial challenge, but it has some restrictions on the domain, performance, and banning built-ins. As the consensus here was to create a separate challenge without those restrictions so that more esolangs can participate, here it goes.

Also, we discussed whether we should close the old one as a duplicate of this, and we decided to leave it open.

\$\endgroup\$

154 Answers 154

3
\$\begingroup\$

Piet + ascii-piet, 24 bytes (4×10=40 codels)

rmttlddqbDlbaltdmu?_ V??

Try Piet online!

Similar to below, but realized that I can remove 1 >. Also, using B2->B1 = I (which is a no-op) gave A2->B2 = D (which safely removes a 0) and a color sharing for 3. Luck based golfing?


Piet + ascii-piet, 27 bytes (5×11=55 codels)

rmttldqbdTl?dckmvfnnN TuDuu

Try Piet online!

The logic is the same as Parcly Taxel's.

Main loop (A1 -> A10 -> B9 -> B1 -> A1):

D * 2 1 r       Mostly no-op, just pushes [2 1]
I               Take input [2 1 n]; becomes a no-op afterwards
                Invariant: [2 prod i]
d 1 -           [2 prod i i-1]
3 1 r d 1 > !   [2 i-1 prod i i<=1]
D               [2 i-1 prod i]; turn right at A2 if n <= 1
* 2 1 r         [2 i-1 prod*i]

After turn right at A2 (A2 -> E2):

x O <halt>      Discard i and print prod

The main trick here is to move the DP+ to the cell A2, and rotate the main loop accordingly. This works because most commands are no-op when there are not enough items on the stack yet.

\$\endgroup\$
3
\$\begingroup\$

TypeScript Type System, 82 bytes

type X<A,B=A>=A extends`1${infer R}`?B extends`1${infer O}`?`${X<R>}${X<A,O>}`:B:1

Try it online!

Quite similar to, but independently derived from noodle man's answer. I also stole their test harness.

This is basically the same as the JavaScript code f = (a, b = a) => a ? b ? f(a, b - 1) + f(a-1) : 0 : 1. The idea here is that we have two accumulators, a and b, where b starts at the value of a. We repeatedly decrement b and add f(a-1) to the total, which results in the factorial of a.

\$\endgroup\$
3
\$\begingroup\$

Uiua, 5 bytes

/×+1⇡

Try it!

    ⇡  # create range [0..input)
  +1   # amend it to [1..input]
/×     # reduce by multiplication
\$\endgroup\$
2
\$\begingroup\$

Keg, -hr, 4 bytes

Ï_∑*

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Shouldn't that be 7 bytes, due to the use of -hr? \$\endgroup\$
    – Oliver
    Commented Feb 7, 2022 at 8:01
  • \$\begingroup\$ @oliver -hr is a command line flag, and it's the site policy that flags don't count towards the byte score. \$\endgroup\$
    – lyxal
    Commented Feb 7, 2022 at 8:19
2
\$\begingroup\$

Pyth, 2 bytes

*F

Try it online!

Alternate solution:

.!
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 1 byte

!

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 3.8, 23 21 bytes

Saved 2 bytes thanks to Bubbler!!!

import math
math.perm

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I think f= can be excluded from the byte count? \$\endgroup\$
    – Bubbler
    Commented Aug 24, 2020 at 23:44
  • \$\begingroup\$ @Bubbler You get so used to things you forget what their orginal purpose was - thanks for the heads up! :D \$\endgroup\$
    – Noodle9
    Commented Aug 24, 2020 at 23:55
  • \$\begingroup\$ What's the point of the math.perm line? I mean, sure, we use math.perm() in the footer, but you can take out that math.perm line and the code will still work. (Then again, maybe the import math line can just be placed in the header, which would leave... 0 bytes? Hm... maybe we should count math.perm.) \$\endgroup\$
    – J-L
    Commented Aug 25, 2020 at 17:41
  • \$\begingroup\$ @J-L In function answers the whole point is to provide enough code to define a function that solves the challenge. Here the function is math.perm so job done. Leaving anything out doesn't provide a full solution. \$\endgroup\$
    – Noodle9
    Commented Aug 25, 2020 at 17:52
  • \$\begingroup\$ Hmm I feel like excluding the f= is somehow wrong, maybe because the interface between the answer and the evaluation code is tightly coupled? Moving f= to the header only makes sense when the first line of code can be used as an expression without assignment, in this case we could wrap math.perm in a lambda and then import math to fit the usual pattern of excluding the assigned variable. If math.perm is allowed to be named in the evaluation code, we could look at the import math statement as a complete solution since it defines math.perm in the current scope. \$\endgroup\$
    – M Virts
    Commented Feb 7, 2022 at 4:56
2
\$\begingroup\$

Japt, 1 byte

l

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 8 bytes

IΠ…·¹∨N¹

Try it online! Link is to verbose version of code. Explanation:

      N     `n` as a number
     ∨      Logical Or
       ¹    Literal `1`
  …·¹       Inclusive range from `1` to `n`
 Π          Take the product
I           Cast to string
            Implicitly print
\$\endgroup\$
2
\$\begingroup\$

Seriously, 2 bytes

,!

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Elixir, 30 bytes

Recursive.

def f(n),do: n>1&&n*(f n-1)||1

Try it online!

\$\endgroup\$
2
\$\begingroup\$

T-SQL, 91 bytes

CREATE FUNCTION dbo.f(@ INT)RETURNS INT AS BEGIN SET @=IIF(@<=1,1,@*dbo.f(@-1))RETURN @ END

Demo

It seems you need to specify a schema (dbo.) in order to make a recursive function :( Perhaps other SQL dialects are shorter.

\$\endgroup\$
2
\$\begingroup\$

ReRegex, 47 bytes

#import math
\b1!/1/(\d+)!/($1-1)!*$1/
#input
!

Defines two regexes;

(\d+)!/($1-1)!*$1/ Looks for a base10 number followed by a !, and replaces it with (n-1)!*n.

\b1!/1/ Replaces any free standing 1!'s with just 1.

The math library then takes care of the subtractions and multiplications. ReRegex will continue attempting its regex operations until it can no-longer modify the text.

The final two lines put the input as n! ready for the operations.

Values greater than 5 work offline, but due to how long they take; do not work on TIO.

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Perl 5 -p, 20 bytes

$\*=$_ for++$\..$_}{

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Alternatively, for 20 bytes as well: $;=$_;$_*=$;while--$ ;-) \$\endgroup\$
    – Dada
    Commented Aug 25, 2020 at 15:13
  • 1
    \$\begingroup\$ Nice to see you back around @Dada! \$\endgroup\$ Commented Aug 25, 2020 at 15:15
  • \$\begingroup\$ $_*="@F"while--$F[0] too (with -a)... there must be something shorter! \$\endgroup\$ Commented Aug 25, 2020 at 15:17
  • \$\begingroup\$ Oh, those don't work with 0 :( \$\endgroup\$ Commented Aug 25, 2020 at 15:29
  • \$\begingroup\$ Indeed, I didn't noticed that :x \$\endgroup\$
    – Dada
    Commented Aug 25, 2020 at 15:32
2
\$\begingroup\$

Muriel, 128 bytes

C:"\";@%(B+\");B:\\\"\"+B+\"*\"+$a+\"\\\";a:\"+$(a-1)+\";C:\\\"\"+|C+C),(a>0)*(&B+2),a*999+&B+2";@"B:\".$(1\";a:"+~+";C:\""+|C+C

Try it online!

Moving another answer from the previous challenge, this time because the answer uses an eval function... in a language where that's the only way to loop.

This is a difficult for a number of reasons. First is Muriel itself, where the only way to do loops is to create a quine and eval it, passing a condition into the code. Next is that large numbers lose precision over time (so the output for \$125!\$ is 1.88267717688893e+209), but the program can't handle that format inside the program itself, so you can't pass large numbers to the next iteration of code. The last problem is that numbers will eventually be so large, the program just renders them as Inf, but thankfully that's far beyond \$125!\$, so we don't have to worry about that.

Explanation:

The first iteration doesn't have to be a complete quine, but can take shortcuts in constructing the actual loop.

C:"\";@%(B+\");B:\\\"\"+B+\"*\"+$a+\"\\\";a:\"+$(a-1)+\";C:\\\"\"+|C+C),(a>0)*(&B+2),a*999+&B+2";

This creates an string version of the loop. This string persists across all iterations of the loop.

@                   # Evaluate the next strings as a new program
 "B:\".$(1\";       # Initialise B as the string ".$(1"
 a:"+~              # Initialise a as the inputted number
 +"C:\""+|C         # Initialise C as the persistent string C
 +C                 # And add the executing part of the program

The resulting program with input 125 looks like (newlines added for clarity)

B:".$(1";
a:125;
C:"\";@%(B+\");B:\\\"\"+B+\"*\"+$a+\"\\\";a:\"+$(a-1)+\";C:\\\"\"+|C+C),(a>0)*(&B+2),a*999+&B+2";
@%(B+");B:\""+B+"*"+$a+"\";a:"+$(a-1)+";C:\""+|C+C),(a>0)*(&B+2),a*999+&B+2

The eval then executes

@                   # Evaluate
 %(     ...     ),(a>0)*(&B+2),a*999+&B+2   # The substring
   B+");                                    # If a is 0, evaluate B
                                            # Otherwise
   B:\""+B+"*"+$a+"\";                      # Concatonate "*a" to the end of B
   a:"+$(a-1)+";                            # Decrement a
   C:\""+|C                                 # Set C to C
   +C                                       # And add the executing part of the program

Eventually, a will reach 0, and B will be evaluated. B will look like:

.                         # Print
 $(       ...         )   # The string form of
   1*125*124*123*...*1    # The factorial
  
  
\$\endgroup\$
2
\$\begingroup\$

COW, 150 bytes

oomMOOMOoMMMmoOmoOmoOMMMMMMMoOmOomOomOoMOOmoOMMMmoOmoOMMMOOOmOoMMMmOoMOOmoOMMMMOOmoOMoOmOoMOomooMMMmOoMOomoomOoMOoMMMmoomoOmoOmoOOOMOOOMOomOOmooMoOOOM

Try it online!

Commented

Four memory blocks are used. Block 1 stores a persistent counter. Blocks 2 and 3 store the temporary loop variables used for multiplication (by repeated addition). Block 4 stores the result.

oom                           # read input into Block 1 
MOO                           # if input is not 0
  MOoMMM                        # decrement and copy
  moOmoOmoOMMMMMMMoOmOomOomOo   # paste and increment to initialise Block 4
  MOO                           # Loop 1: from Block 1 value down to 1
    moOMMM                        # set Block 2 to Block 1 value
    moOmoOMMMOOOmOoMMM            # set Block 3 to Block 4 value and zero Block 4
    mOoMOO                        # Loop 2: from Block 2 value down to 1
      moOMMMMOO                     # Loop 3: as many times as Block 3 value
        moOMoO                        # increment Block 4
      mOoMOomooMMM                  # end Loop 3
    mOoMOomoo                     # end Loop 2
  mOoMOoMMMmoo                  # end Loop 1
  moOmoOmoOOOM                  # print Block 4 value
  OOOMOomOO                     # exit
moo                           # (only get here if input is 0)
MoOOOM                        # print 1
\$\endgroup\$
2
\$\begingroup\$

Scala 2.12, 14 bytes

1 to _ product

This is a function expression, where the underscore is the parameter. 1 to _ creates a range object, and product calculates the product of all numbers.

\$\endgroup\$
5
  • \$\begingroup\$ May I ask why it's Scala 2.12 specifically? It looks like that code should work in other versions too. \$\endgroup\$
    – user
    Commented Sep 5, 2020 at 20:26
  • \$\begingroup\$ @user In Scala 2.13, you get an error mesage: error: postfix operator product needs to be enabled by making the implicit value scala.language.postfixOps visible. It should work in older versions, though. \$\endgroup\$
    – corvus_192
    Commented Sep 7, 2020 at 7:54
  • \$\begingroup\$ You can also add the compiler flag -language:postfixOps, though. That’s not part of the byte count, right? \$\endgroup\$
    – user
    Commented Sep 7, 2020 at 11:22
  • \$\begingroup\$ @user I think the common practice is to count compiler flags codegolf.meta.stackexchange.com/q/19. \$\endgroup\$
    – corvus_192
    Commented Sep 8, 2020 at 9:53
  • \$\begingroup\$ Oh, that’s too bad. \$\endgroup\$
    – user
    Commented Sep 9, 2020 at 0:12
2
\$\begingroup\$

Forth (gforth), 30 bytes

: f 1 swap 0 ?do i 1+ * loop ;

Try it online!

Code Explanation

: f          \ start a new word definition
  1 swap 0   \ create accumulator and set up loop parameters
  ?do        \ start a conditional counted loop from 0 to n
    i 1+ *   \ multiply accumulator by loop index + 1
  loop       \ end counted loop
;            \ end word definition 
\$\endgroup\$
1
  • \$\begingroup\$ 28 bytes using a backward loop. \$\endgroup\$
    – Bubbler
    Commented Nov 2, 2020 at 0:50
2
\$\begingroup\$

F#, 26 bytes, by Laikoni

fun x->List.fold(*)1[1..x]

Try it online!

F#, 35 bytes

let rec f=function|0->1|x->x*f(x-1)

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 26 bytes: fun x->List.fold(*)1[1..x] \$\endgroup\$
    – Laikoni
    Commented Aug 28, 2020 at 13:03
  • \$\begingroup\$ Very nice :) Why don't you post it yourself? Until then, I've updated my answer. \$\endgroup\$
    – Brunner
    Commented Aug 29, 2020 at 17:53
2
\$\begingroup\$

Arn, 2 bytes

↓;

Try it!

Unpacked: .fact. Passes STDIN (_) into the factorial function via the . infix

3 byte solution:

A→.

Unpacked: *\~

  \      Fold with
*        Multiplication
    ~    1-range
      _  Variable initialized to STDIN; implied
\$\endgroup\$
1
  • \$\begingroup\$ There can't be shorter answer. \$\endgroup\$
    – gildux
    Commented Jan 16, 2023 at 8:16
2
\$\begingroup\$

Flurry -nii, 14 bytes

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

Try it online!

Takes single number from the stack and prints its factorial from the return value.

The online interpreter implements certain arithmetic shortcuts, so it computes and prints 125! in an instant.

How it works

Iterate through 1 to n using the stack height and multiply all of them to the starting value of 1.

// n is the only content of the stack at program start
// 1 is popped from empty stack
main = pop push-mul pop
     = n push-mul 1

// height yields 1 to n, since it is called after a push
// <a b> = a * b (where a, b are Church numerals)
push-mul = \x. <(push x) height>
\$\endgroup\$
2
\$\begingroup\$

Labyrinth, 16 bytes

?+1#*
(: (;
 @!;

Try it online!

Utilizes two loops, one to duplicate and decrement the input until zero, then one to multiply all the items on the stack.

\$\endgroup\$
2
\$\begingroup\$

Husk, 1 byte

Π

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ OMG only one byte... \$\endgroup\$
    – gildux
    Commented Jan 16, 2023 at 8:17
  • \$\begingroup\$ it's nothing special. The answers which have more bytes are better by a large margin. \$\endgroup\$
    – Razetime
    Commented Jan 17, 2023 at 14:16
2
\$\begingroup\$

ARM Thumb-2, 12 bytes

2101 b110 4341 3801 d1fc 4770

Commented assembly:

        .syntax unified
        .arch armv6t2
        .thumb
        .globl factorial
        .thumb_func
        // input: r0
        // output: r1
factorial:
        // accumulator starts at 1
        movs    r1, #1
        // skip to end if r0 is zero
        cbz     r0, .Lend
.Lloop:
        // r1 *= r0
        muls    r1, r0
        // while (--r0)
        subs    r0, #1
        bne     .Lloop
.Lend:
        // return
        bx      lr

Standard iterative approach.

Takes a 32-bit integer in r0, returns a 32-bit integer in r1.

ARM Thumb-2, 20 bytes

2201 2300 b128 fba2 2100 fb03 1300 3801 d1f9 4770

Commented assembly:

        .globl factorial64
        .thumb_func
        // input: r0
        // output: {r2, r3}
factorial64:
        // accumulator starts at 1
        movs    r2, #1
        movs    r3, #0
        // skip to end if r0 is zero
        cbz     r0, .Lend64
.Lloop64:
        // {r2, r3} *= r0
        // tmp = (u64)r2 * r0
        umull   r2, r1, r0, r2
        // {r2, r3} = tmp + (r3 * r0 << 32)
        mla     r3, r3, r0, r1
        // while (--r0)
        subs    r0, #1
        bne     .Lloop64
.Lend64:
        // return
        bx      lr

This version uses 64-bit arithmetic, at the cost of 8 bytes. It is only 2 more instructions, but two of those instructions are now wide instructions. 😭

Takes a 32-bit integer in r0 and returns a 64-bit integer in {r2, r3} (easy to forward to printf)

\$\endgroup\$
1
  • \$\begingroup\$ OMG, you beat x86-16?! \$\endgroup\$
    – user99151
    Commented Feb 11, 2021 at 7:07
2
\$\begingroup\$

Assembly (MIPS, SPIM), 78 bytes, 6*9 = 54 assembled bytes

main:li$2,5
syscall
li$4,1
f:beqz$2,g
mul$4,$4,$2
sub$2,1
b f
g:li$2,1
syscall

Try it online!

This is a significant optimization of this answer, but the account was deleted.

Specifically, this makes the following changes:

  • It compares once at the top of the loop, using an unconditional branch at the bottom
  • It uses the numerical register names which are shorter
  • It removes spaces between mnemonics, as SPIM accepts this
  • It removes the second operand from sub

Otherwise, the logic is identical.

\$\endgroup\$
2
\$\begingroup\$

Phooey, 15 bytes

=>&.[@<*>-1]<$i

Try it online!

=>&.[@<*>-1]<$i # stack tape 
=               #   (0)  >a    0     acc = 1
 >              #   (0)   a   >0     move left
  &.            #   (0)   a   >n     read int
    [      ]    #   (0)   a   >n     loop while n != 0
     @          #    n    a   >n         push n
      <*>       #   (0)   a*n >n         multiply acc by n (popping from stack)
         -1     #   (0)   a*n >n-1       subtract 1 from n
            <   #   (0)  >res 0      go right to the result
             $i #   (0)  >res 0      print as integer

Since Phooey uses int64_t, this supports up to 20.

\$\endgroup\$
2
+250
\$\begingroup\$

Factor + math.factorials, 6 bytes

[ n! ]

Try it online!

Thanks to @Bubbler for -9 bytes

Factor + math.factorials, 15 bytes

[ factorial . ]

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ There's n! which is a synonym of factorial, and you don't need to print the result, so simply n! is a valid built-in submission. (You don't need to wrap it in a quotation, as a built-in submission is scored by its name.) \$\endgroup\$
    – Bubbler
    Commented Mar 31, 2021 at 3:34
2
\$\begingroup\$

jq, 10 bytes

.+1|tgamma

Uses the gamma function Γ(n) = (n - 1)!

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think |ceil is not necessary since floating point imprecision is allowed. \$\endgroup\$
    – Bubbler
    Commented Sep 2, 2021 at 23:50
2
\$\begingroup\$

Cascade, 18 bytes

#1]*
\aa?
(\&;
a ?

Try it online!

Golfed version by Jo King.

A program without @ starts at the top-left corner. The main difference with my version is that a is decremented under the second branch, not first:

  ?
  ] 
 a ?
  &;(
    a

Cascade, 22 bytes

? @
]*#1
)(|a
a?\
&;a\

Try it online!

Solved as part of LYAL 2021-09-29.

How it works

Cascade programs start the execution at the entry point @.

? @   The main program prints (#) the result of the huge loop
  #   starting at `?`
  | 
  \
   \

 ?    (grid rotated once for clarity)
 ]    On entry, the if-clause is run:
a (   Push to the stack "a" the decrement of...
  ?   If EOF, the top value of "a", otherwise the input from stdin
 &;a

 ?    If the above is not positive, return 1;
1 *   Otherwise return (increment of a) times
 ) |  the next invocation of the main loop
 a \
\
\$\endgroup\$
2
\$\begingroup\$

Python 3, 25 bytes

f=lambda n:n<1or n*f(n-1)

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ This does not work. This outputs True for 0 when it should output 1. You can fix this by replacing n<1 with +(n<1) to cast it to an integer. You can also remove f= to save 2 bytes. \$\endgroup\$ Commented Aug 24, 2023 at 9:42
  • \$\begingroup\$ @TheEmptyStringPhotographer thanks for your feedback! In Python, True == 1, so it is generally accepted to leave it at that. Also, the f= is required because the lambda is recursive. \$\endgroup\$
    – Jitse
    Commented Aug 31, 2023 at 13:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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