18
votes
\$\begingroup\$

The challenge:

Write a program or a function that inputs a positive number and returns its factorial.

Note: This is a question. Please do not take the question and/or answers seriously. More information here. Every question is also a question, so the highest voted answer wins.

\$\endgroup\$

locked by Doorknob May 12 '14 at 0:13

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site, so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. More info: help center.

Read more about locked posts here.

  • 6
    \$\begingroup\$ See also The Evolution of Haskell programmer. \$\endgroup\$ – Petr Pudlák Dec 29 '13 at 7:46
  • 4
    \$\begingroup\$ -1, sorry, because we're getting a huge flood of these code trolling questions and this does not really add anything new to them \$\endgroup\$ – Doorknob Dec 29 '13 at 11:25
  • \$\begingroup\$ Related: codegolf.stackexchange.com/questions/1635/forking-factorials \$\endgroup\$ – Paul Dec 30 '13 at 10:08
  • \$\begingroup\$ Code-trolling is in the process of being removed, as per the official stance. This question has a fair amount of votes with many answers, many of which are extremely highly voted. It recieved just over 50% "delete" votes on the poll, but it is unique in that it recieved so many answers and votes, so I am locking it for historical significance. \$\endgroup\$ – Doorknob May 12 '14 at 0:13

61 Answers 61

46
votes
\$\begingroup\$

This is a very simple numerical computing problem that we can solve with Stirling's approximation:

Stirling's approximation formula

As you can see, that formula features a square root, which we will also need a way to approximate. We will choose the so-called "Babylonian method" for that because it is arguably the simplest one:

Babylonian method

Note that computing the square root this way is a good example of recursion.

Putting it all together in a Python program gives us the following solution to your problem:

def sqrt(x, n): # not the same n as below
    return .5 * (sqrt(x, n - 1) + x / sqrt(x, n - 1)) if n > 0 else x

n = float(raw_input())
print (n / 2.718) ** n * sqrt(2 * 3.141 * n, 10)

With a simple modification the above program can output a neat table of factorials:

1! =    0.92215
2! =    1.91922
3! =    5.83747
4! =   23.51371
5! =  118.06923
6! =  710.45304
7! = 4983.54173
8! = 39931.74015
9! = 359838.58817

This method should be sufficiently accurate for most applications.

\$\endgroup\$
  • 16
    \$\begingroup\$ +1 The simplicity and accuracy of this method makes it a clear winner \$\endgroup\$ – Joe the Person Dec 31 '13 at 12:09
44
votes
\$\begingroup\$

C#

Sorry, but I hate recursive function.

public string Factorial(uint n) {
    return n + "!";
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Technically, you've satisfied the brief! ;) +1 for brief abuse \$\endgroup\$ – WallyWest Jan 6 '14 at 5:30
36
votes
\$\begingroup\$

Java

public int factorial ( int n ) {
switch(n){
case 0: return 1;
case 1: return 1;
case 2: return 2;
case 3: return 6;
case 4: return 24;
case 5: return 120;
case 6: return 720;
case 7: return 5040;
case 8: return 40320;
case 9: return 362880;
case 10: return 3628800;
case 11: return 39916800;
case 12: return 479001600;
default : throw new IllegalArgumentException();
}
}
\$\endgroup\$
  • 16
    \$\begingroup\$ I tried it - very efficient. Will ship with next release. :) \$\endgroup\$ – Johannes Dec 29 '13 at 22:33
  • \$\begingroup\$ Beside the "magical numbers syndrom", this could actually be a good implementation as long as n<13, much less stacks. Write it "case 4: return 4*3*2;" and you'd have a decent class, much faster than the old recursive one. \$\endgroup\$ – Fabinout Jan 30 '14 at 17:16
  • 6
    \$\begingroup\$ @Fabinout, the implementation is correct even for n>=13. 13!>Integer.MAX_VALUE. \$\endgroup\$ – emory Jan 30 '14 at 21:11
21
votes
\$\begingroup\$

Python

Of course the best way how to solve any problem is to use regular expressions:

import re

# adapted from http://stackoverflow.com/q/15175142/1333025
def multiple_replace(dict, text):
  # Create a regular expression  from the dictionary keys
  regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
  # Repeat while any replacements are made.
  count = -1
  while count != 0:
    # For each match, look-up corresponding value in dictionary.
    (text, count) = regex.subn(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
  return text

fdict = {
    'A': '@',
    'B': 'AA',
    'C': 'BBB',
    'D': 'CCCC',
    'E': 'DDDDD',
    'F': 'EEEEEE',
    'G': 'FFFFFFF',
    'H': 'GGGGGGGG',
    'I': 'HHHHHHHHH',
    'J': 'IIIIIIIIII',
    'K': 'JJJJJJJJJJJ',
    'L': 'KKKKKKKKKKKK',
    'M': 'LLLLLLLLLLLLL',
    'N': 'MMMMMMMMMMMMMM',
    'O': 'NNNNNNNNNNNNNNN',
    'P': 'OOOOOOOOOOOOOOOO',
    'Q': 'PPPPPPPPPPPPPPPPP',
    'R': 'QQQQQQQQQQQQQQQQQQ',
    'S': 'RRRRRRRRRRRRRRRRRRR',
    'T': 'SSSSSSSSSSSSSSSSSSSS',
    'U': 'TTTTTTTTTTTTTTTTTTTTT',
    'V': 'UUUUUUUUUUUUUUUUUUUUUU',
    'W': 'VVVVVVVVVVVVVVVVVVVVVVV',
    'X': 'WWWWWWWWWWWWWWWWWWWWWWWW',
    'Y': 'XXXXXXXXXXXXXXXXXXXXXXXXX',
    'Z': 'YYYYYYYYYYYYYYYYYYYYYYYYYY'}

def fact(n):
    return len(multiple_replace(fdict, chr(64 + n)))

if __name__ == "__main__":
    print fact(7)
\$\endgroup\$
  • 1
    \$\begingroup\$ Of course indeed :) \$\endgroup\$ – Pierre Arlaud Jan 3 '14 at 21:27
15
votes
\$\begingroup\$

Haskell

Short code is efficient code, so try this.

fac = length . permutations . flip take [1..]

Why it's trolling:

I'd laugh at any coder who wrote this... The inefficiency is beautiful. Also probably incomprehensible to any Haskell programmer who actually can't write a factorial function.

Edit: I posted this a while ago now, but I thought I'd clarify for future people and people who can't read Haskell.

The code here takes the list of the numbers 1 to n, creates the list of all permutations of that list, and returns the length of that list. On my machine it takes about 20 minutes for 13!. And then it ought to take four hours for 14! and then two and a half days for 15!. Except that at some point in there you run out of memory.

Edit 2: Actually you probably won't run out of memory due to this being Haskell (see the comment below). You might be able to force it to evaluate the list and hold it in memory somehow, but I don't know enough about optimizing (and unoptimizing) Haskell to know exactly how to do that.

\$\endgroup\$
  • \$\begingroup\$ Hideous and yet so elegant, all at the same time. \$\endgroup\$ – PLL Jan 10 '14 at 11:21
  • 1
    \$\begingroup\$ Are you sure about the memory issue? At any one point, you need to hold in memory: - the list [1..n]. - One particular permutation of [1..n], consed to a thunk for the rest of the permutations (polynomial in n). - An accumulator for the length function. \$\endgroup\$ – John Dvorak Mar 11 '14 at 6:47
  • \$\begingroup\$ Fair point, probably not actually. Didn't really think about it too much. I'll add a comment at the bottom. \$\endgroup\$ – jgon Mar 17 '14 at 18:23
10
votes
\$\begingroup\$

C#

Since this is a math problem, it makes sense to use an application specifically designed to solve math problems to do this calculation...

Step 1:

Install MATLAB. A trial will work, I think, but this super-complicated problem is likely important enough to merit purchasing the full version of the application.

Step 2:

Include the MATLAB COM component in your application.

Step 3:

public string Factorial(uint n) {
    MLApp.MLApp matlab = new MLApp.MLApp();
    return matlab.Execute(String.Format("factorial({0})", n);
}
\$\endgroup\$
  • \$\begingroup\$ Matlab for students starts at $100. Professional versions or site licenses can go way into the thousands. \$\endgroup\$ – Moshe Katz Dec 30 '13 at 5:43
  • 4
    \$\begingroup\$ Moshe Katz - justified because factorials. \$\endgroup\$ – Mike H. Jan 22 '14 at 21:57
9
votes
\$\begingroup\$

C#

Factorials are a higher level math operation that can be difficult to digest all in one go. The best solution in programming problems like this, is to break down one large task into smaller tasks.

Now, n! is defined as 1*2*...*n, so, in essence repeated multiplication, and multiplication is nothing but repeated addition. So, with that in mind, the following solves this problem:

long Factorial(int n)
{
    if(n==0)
    {
        return 1;
    }

    Stack<long> s = new Stack<long>();
    for(var i=1;i<=n;i++)
    {
        s.Push(i);
    }
    var items = new List<long>();
    var n2 = s.Pop();
    while(s.Count >0)
    {
        var n3 = s.Pop();
        items.AddRange(FactorialPart(n2,n3));
        n2 = items.Sum();
    }
    return items.Sum()/(n-1);
}

IEnumerable<long> FactorialPart(long n1, long n2)
{
    for(var i=0;i<n2;i++){
        yield return n1;
    }
}
\$\endgroup\$
  • \$\begingroup\$ You have a bottleneck sending all this through one CPU or core, which I think I may have solved in my answer :-) \$\endgroup\$ – Paul Dec 30 '13 at 10:19
9
votes
\$\begingroup\$
#include <math.h>

int factorial(int n)
{
    const double g = 7;
    static const double p[] = { 0.99999999999980993, 676.5203681218851,
                                -1259.1392167224028, 771.32342877765313,
                                -176.61502916214059, 12.507343278686905,
                                -0.13857109526572012, 9.9843695780195716e-6,
                                1.5056327351493116e-7 };
    double z = n - 1 + 1;
    double x = p[0];
    int i;
    for ( i = 1; i < sizeof(p)/sizeof(p[0]); ++i )
        x += p[i] / (z + i);
    return sqrt(2 * M_PI) * pow(z + g + 0.5, z + 0.5)  * exp(-z -g -0.5) * x + 0.5;
}

Trolls:

  • A 100% correct way of computing factorial that completely misses the point of either doing it iteratively or recursively.
  • You have no idea why it works and could not generalize it to do anything else.
  • More costly than just computing it with integer math.
  • The most obvious "suboptimal" code (z = n - 1 + 1) is actually self-documenting if you know what's going on.
  • For extra trolling I should compute p[] using a recursive calculation of the series coefficients!

(It's the Lanczos approximation of the gamma function)

\$\endgroup\$
  • \$\begingroup\$ Is there any point in - 1 + 1 here? My compiler optimizes it (it's not floating point number where optimizing code like this could be dangerous), so it appears to be unneeded. \$\endgroup\$ – Konrad Borowski Jan 14 '14 at 14:36
  • 4
    \$\begingroup\$ @xfix: double z = n - 1 is part of the approximation of the gamma function. The + 1 is from the relationship that gamma(n + 1) = n! for integer n. \$\endgroup\$ – Ben Jackson Jan 14 '14 at 14:39
9
votes
\$\begingroup\$

We all know from college that the most efficient way to calculate a multiplication is through the use of logarithms. After all, why else would people use logarithm tables for hundreds of years?

So from the identity a*b=e^(log(a)+log(b)) we form the following Python code:

from math import log,exp

def fac_you(x):
    return round(exp(sum(map(log,range(1,x+1)))))

for i in range(1,99):
    print i,":",fac_you(i)

It creates a list of numbers from 1 to x, (the +1 is needed because Python sucks) calculates the logarithm of each, sums the numbers, raises the e to the power of the sum and finally rounds the value to the nearest integer (because Python sucks). Python has a built-in function for calculating factorials, but it only works for integers, so it can't produce big numbers (because Python sucks). This is why the function above is needed.

Btw, a general tip for students is that if something doesn't work as expected, it's probably because the language sucks.

\$\endgroup\$
  • \$\begingroup\$ Wish I could give some extra votes there for the description, but Python sucks \$\endgroup\$ – Mark K Cowan Jan 24 '14 at 14:45
  • 1
    \$\begingroup\$ I laughed at "fac you" \$\endgroup\$ – Number9 Mar 17 '14 at 19:56
8
votes
\$\begingroup\$

Unfortunately, Javascript lacks a built-in way to compute the factorial. But, you can use its meaning in combinatorics to determine the value nevertheless:

The factorial of a number n is the number of permutations of an list of that size.

So, we can generate every list of n-digit number, check if it is a permutation, and if so, increment a counter:

window.factorial = function($nb_number) {
  $nb_trials = 1
  for($i = 0; $i < $nb_number; $i++) $nb_trials *= $nb_number
  $nb_successes = 0
  __trying__:
  for($nb_trial = 0; $nb_trial < $nb_trials; $nb_trial++){
    $a_trial_split = new Array
    $nb_tmp = $nb_trial
    for ($nb_digit = 0; $nb_digit < $nb_number; $nb_digit++){
      $a_trial_split[$nb_digit] = $nb_tmp - $nb_number * Math.floor($nb_tmp / $nb_number)
      $nb_tmp = Math.floor($nb_tmp / $nb_number)
    }
    for($i = 0; $i < $nb_number; $i++)
      for($j = 0; $j < $nb_number; $j++)
        if($i != $j)
          if($a_trial_split[$i] == $a_trial_split[$j])
            continue __trying__
    $nb_successes += 1
  }
  return $nb_successes
}

alert("input a number")
document.open()
document.write("<input type = text onblur = alert(factorial(parseInt(this.value))))>")
document.close()


Trolls:

  • Types hungarian notation, snake_case and unneccessary sigils. How evil is that?
  • Invented my own convention for jump labels, incompatible with the current use of this convention.
  • Every possible variable is accidentally global.
  • The solution is not O(n), not O(n!), but O(n^n). This alone would have sufficed to qualify here.
  • Incrementing a number and then converting as base-n is a bad way to generate a list of sequences. Even if we did want duplicates. Mysteriously breaking for n > 13 is not the only reason.
  • Of course we could have used number.toString(base), but that doesn't work for bases above 36. Yes, I know 36! is a lot, but still...
  • Did I mention Javascript had the modulus operator? Or Math.pow? No? Oh well.
  • Refusing to use ++ outside of for-loops makes it even more mysterious. Also, == is bad.
  • Deeply nested braceless looping constructs. Also, nested conditionals instead of AND. Also, the outer condition could have been avoided by ending the inner loop at $i.
  • The functions new Array, document.write (with friends) and alert (instead of a prompt or an input label) form a complete trifecta of function choice sins. Why is the input added dynamically after all?
  • Inline event handlers. Oh, and deep piping is hell to debug.
  • Unquoted attributes are fun, and the spaces around = make them even harder to read.
  • Did I already mention I hate semicolons?
\$\endgroup\$
8
votes
\$\begingroup\$

Ruby and WolframAlpha

This solution uses the WolframAlpha REST API to calculate the factorial, with RestClient to fetch the solution and Nokogiri to parse it. It doesn't reinvent any wheels and uses well tested and popular technologies to get the result in the most modern way possible.

require 'rest-client'
require 'nokogiri'

n = gets.chomp.to_i
response = Nokogiri::XML(RestClient.get("http://api.wolframalpha.com/v2/query?input=#{n}!&format=moutput&appid=YOUR_APP_KEY"))
puts response.xpath("//*/moutput/text()").text
\$\endgroup\$
7
votes
\$\begingroup\$

Javascript

Javascript is a functional programming language, this means you have to use functions for everything because its faster.

function fac(n){
    var r = 1,
        a = Array.apply(null, Array(n)).map(Number.call, Number).map(function(n){r = r * (n + 1);});
    return r;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Can you explain? \$\endgroup\$ – Mhmd Dec 31 '13 at 15:55
  • 7
    \$\begingroup\$ 1 is not a function. Your code is thus slow. \$\endgroup\$ – Pierre Arlaud Jan 2 '14 at 13:59
  • 4
    \$\begingroup\$ @ArlaudPierre r = -~(function(){}) will surely solve that. \$\endgroup\$ – nitro2k01 Jan 5 '14 at 11:49
  • 4
    \$\begingroup\$ I am on a work machine so I don't really want to install this language. Where can I find a version that will run in my browser? \$\endgroup\$ – joeytwiddle Jan 13 '14 at 20:43
  • 3
    \$\begingroup\$ I'm a bit scared of using Google because my boss has an account with them, and I don't want him to know I'm playing golf at work. I was looking for an extension for Firefox that could run Javascript, but I can't seem to find one. Some of my friends run Javascript on jsfiddle.net but that's using somebody else's electricity which is a bit like stealing. My mum said I shouldn't hang around with people like that, but they are my friends so what can I do? Anyway she sometimes takes more creamer than she needs. Thanks for the tips, I use Ctrl-Shift-J or K in Firefox. Disclaimer: #comment-trolling \$\endgroup\$ – joeytwiddle Jan 13 '14 at 21:54
5
votes
\$\begingroup\$

Using Bogo-Sort in Java

public class Factorial {
    public static void main(String[] args) {
        //take the factorial of the integers from 0 to 7:
        for(int i = 0; i < 8; i++) {
            System.out.println(i + ": " + accurate_factorial(i));
        }
    }

    //takes the average over many tries
    public static long accurate_factorial(int n) {
        double sum = 0;
        for(int i = 0; i < 10000; i++) {
            sum += factorial(n);
        }
        return Math.round(sum / 10000);
    }

    public static long factorial(int n) {
        //n! = number of ways to sort n
        //bogo-sort has O(n!) time, a good approximation for n!
        //for best results, average over several passes

        //create the list {1, 2, ..., n}
        int[] list = new int[n];
        for(int i = 0; i < n; i++)
            list[i] = i;

        //mess up list once before we begin
        randomize(list);

        long guesses = 1;

        while(!isSorted(list)) {
            randomize(list);
            guesses++;
        }

        return guesses;
    }

    public static void randomize(int[] list) {
        for(int i = 0; i < list.length; i++) {
            int j = (int) (Math.random() * list.length);

            //super-efficient way of swapping 2 elements without temp variables
            if(i != j) {
                list[i] ^= list[j];
                list[j] ^= list[i];
                list[i] ^= list[j];
            }
        }
    }

    public static boolean isSorted(int[] list) {
        for(int i = 1; i < list.length; i++) {
            if(list[i - 1] > list[i])
                return false;
        }
        return true;
    }
}

This actually works, just very slowly, and it isn't accurate for higher numbers.

\$\endgroup\$
4
votes
\$\begingroup\$

PERL

Factorial can be a hard problem. A map/reduce like technique -- just like Google uses -- can split up the math by forking off a bunch of processes and collecting the results. This will make good use of all those cores or cpus in your system on a cold winter's night.

Save as f.perl and chmod 755 to make sure you can run it. You do have the Pathologically Eclectic Rubbish Lister installed, don't you?

#!/usr/bin/perl -w                                                              
use strict;
use bigint;
die "usage: f.perl N (outputs N!)" unless ($ARGV[0] > 1);
print STDOUT &main::rangeProduct(1,$ARGV[0])."\n";
sub main::rangeProduct {
    my($l, $h) = @_;
    return $l    if ($l==$h);
    return $l*$h if ($l==($h-1));
    # arghhh - multiplying more than 2 numbers at a time is too much work       
    # find the midpoint and split the work up :-)                               
    my $m = int(($h+$l)/2);
    my $pid = open(my $KID, "-|");
      if ($pid){ # parent                                                       
        my $X = &main::rangeProduct($l,$m);
        my $Y = <$KID>;
        chomp($Y);
        close($KID);
        die "kid failed" unless defined $Y;
        return $X*$Y;
      } else {
        # kid                                                                   
        print STDOUT &main::rangeProduct($m+1,$h)."\n";
        exit(0);
    }
}

Trolls:

  • forks O(log2(N)) processes
  • doesn't check how many CPUs or cores you have
  • Hides lots of bigint/text conversions that occur in every process
  • A for loop is often faster than this code
\$\endgroup\$
  • \$\begingroup\$ TIL that in perl ARGV[0] is actually the first argument and not the script! \$\endgroup\$ – ThinkChaos Jan 5 '14 at 11:17
  • \$\begingroup\$ @plg I believe $0 might contain the script filename, but that is not the same as $ARGV[0] \$\endgroup\$ – Paul Jan 5 '14 at 11:30
  • \$\begingroup\$ Yep, that's what I read. I just found it surprising that in perl it's not $ARGV[0] because most languages I know a bit have it there \$\endgroup\$ – ThinkChaos Jan 5 '14 at 11:35
4
votes
\$\begingroup\$

Python

Just an O(n!*n^2) algorithm to find the factorial. Base case handled. No overflows.

def divide(n,i):
    res=0
    while n>=i:
         res+=1
         n=n-i
    return res

def isdivisible(n,numbers):
    for i in numbers:
         if n%i!=0:
             return 0
         n=divide(n,i)
    return 1

def factorial(n):
    res = 1
    if n==0: return 1 #Handling the base case
    while not isdivisible(res,range(1,n+1)):
         res+=1
    return res
\$\endgroup\$
3
votes
\$\begingroup\$

Well, there is an easy solution in Golfscript. You could use a Golfscript interpreter and run this code:

.!+,1\{)}%{*}/

Easy huh :) Good luck!

\$\endgroup\$
  • 2
    \$\begingroup\$ I don't know GolfScript, but this one disappoints me... Based on the other GolfScript examples on this site, I would have expected the answer to be ! \$\endgroup\$ – Mr Lister Jan 11 '14 at 7:19
  • 1
    \$\begingroup\$ That is the negation operator. 0 becomes 1 and everything else becomes 0. \$\endgroup\$ – Martijn Courteaux Jan 11 '14 at 12:20
3
votes
\$\begingroup\$

Mathematica

factorial[n_] := Length[Permutations[Table[k, {k, 1, n}]]]

It doesn't seem work for numbers larger than 11, and factorial[11] froze up my computer.

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

Ruby

f=->(n) { return 1 if n.zero?; t=0; t+=1 until t/n == f[n-1]; t }

The slowest one-liner I can imagine. It takes 2 minutes on an i7 processor to calculate 6!.

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

The correct approach for these difficult math problems is a DSL. So I'll model this in terms of a simple language

data DSL b a = Var x (b -> a)
             | Mult DSL DSL (b -> a)
             | Plus DSL DSL (b -> a)
             | Const Integer (b -> a) 

To write our DSL nicely, it's helpful to view it as a free monad generated by the algebraic functor

F X = X + F (DSL b (F X)) -- Informally define + to be the disjoint sum of two sets

We could write this in Haskell as

Free b a = Pure a
         | Free (DSL b (Free b a))

I will leave it to the reader to derive the trivial implementation of

join   :: Free b (Free b a) -> Free b a
return :: a -> Free b a
liftF  :: DSL b a -> Free b a

Now we can descibe an operation to model a factorial in this DSL

factorial :: Integer -> Free Integer Integer
factorial 0 = liftF $ Const 1 id
factorial n = do
  fact' <- factorial (n - 1)
  liftF $ Mult fact' n id

Now that we've modeled this, we just need to provide an actual interpretation function for our free monad.

denote :: Free Integer Integer -> Integer
denote (Pure a) = a
denote (Free (Const 0 rest)) = denote $ rest 0
...

And I'll leave the rest of the denotation to the reader.

To improve readability, it's sometimes helpful to present a concrete AST of the form

data AST = ConstE Integer
         | PlusE AST AST
         | MultE AST AST

and then right a trivial reflection

reify :: Free b Integer -> AST

and then it's straightforward to recursively evaluate the AST.

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

Python

Below is a Python version of the solution, which is not limited to the 32 bit (or 64 bit on a very recent system) limit for integer numbers in Python. To get around this limitation, we shall use a string as input and output for the factorial routine and internally split the string in it's digits to be able to perform the multiplication.

So here is the code: the getDigits function splits a string representing a number in to its digits, so "1234" becomes [ 4, 3, 2, 1 ] (the reverse order just makes the increase and multiply functions simpler). The increase function takes such a list and increases it by one. As the name suggests, the multiply function multiplies, e.g. multiply([2, 1], [3]) returns [ 6, 3 ] because 12 times 3 is 36. This works in the same way as you would multiply something with pen and paper.

Then finally, the factorial function uses these helper functions to calculate the actual factorial, for example factorial("9") gives "362880" as its output.

import copy

def getDigits(n):
    digits = []
    for c in n:
        digits.append(ord(c) - ord('0'))

    digits.reverse()
    return digits

def increase(d):
    d[0] += 1
    i = 0
    while d[i] >= 10:
        if i == len(d)-1:
            d.append(0)

        d[i] -= 10
        d[i+1] += 1
        i += 1

def multiply(a, b):
    subs = [ ]
    s0 = [ ]
    for bi in b:

        s = copy.copy(s0)
        carry = 0
        for ai in a:
            m = ai * bi + carry
            s.append(m%10)
            carry = m//10

        if carry != 0:
            s.append(carry)

        subs.append(s)
        s0.append(0)

    done = False
    res = [ ]
    termsum = 0
    pos = 0
    while not done:
        found = False
        for s in subs:
            if pos < len(s):
                found = True
                termsum += s[pos]

        if not found:
            if termsum != 0:
                res.append(termsum%10)
                termsum = termsum//10
            done = True
        else:
            res.append(termsum%10)
            termsum = termsum//10
            pos += 1

    while termsum != 0:
        res.append(termsum%10)
        termsum = termsum//10

    return res

def factorial(x):
    if x.strip() == "0" or x.strip() == "1":
        return "1"

    factorial = [ 1 ]
    done = False
    number = [ 1 ]
    stopNumber = getDigits(x)
    while not done:
        if number == stopNumber:
            done = True

        factorial = multiply(factorial, number)
        increase(number)

    factorial.reverse()

    result = ""
    for c in factorial:
        result += chr(c + ord('0'))

    return result

print factorial("9")

Notes

In python an integer doesn't have a limit, so if you'd like to do this manually you can just do

fac = 1
for i in range(2,n+1): 
    fac *= i

There's also the very convenient math.factorial(n) function.

This solution is obviously far more complex than it needs to be, but it does work and in fact it illustrates how you can calculate the factorial in case you are limited by 32 or 64 bits. So while nobody will believe this is the solution you've come up with for this simple (at least in Python) problem, you can actually learn something.

\$\endgroup\$
  • \$\begingroup\$ There is no limit on integer numbers in Python... right? You might need to explain this better. \$\endgroup\$ – Riking Dec 30 '13 at 8:49
  • \$\begingroup\$ @Riking Yes, in python there's no limit for integers. I've added a few notes to make it more clear. \$\endgroup\$ – brm Dec 30 '13 at 9:25
2
votes
\$\begingroup\$

Python

The most reasonable solution is clearly to check through all numbers until you find the one which is the factorial of the given number.

print('Enter the number')
n=int(input())
x=1
while True:
    x+=1
    tempx=int(str(x))
    d=True
    for i in range(1, n+1):
        if tempx/i!=round(tempx/i):
            d=False
        else:
            tempx/=i
    if d:
        print(x)
        break
\$\endgroup\$
2
votes
\$\begingroup\$

A most elegant recursive solution in C

Every one knows the most elegant solutions to factorials are recursive.

Factorial:

0! = 1
1! = 1
n! = n * (n - 1)!

But multiplication can also be defined recursively as successive additions.

Multiplication:

n * 0 = 0
n * 1 = n
n * m = n + n * (m - 1)

And so can addition as successive incrementations.

Addition:

n + 0 = n
n + 1 = (n + 1)
n + m = (n + 1) + (m - 1)

In C, we can use ++x and --x to handle the primitives (x + 1) and (x - 1) respectively, so we have everything defined.

#include <stdlib.h>
#include <stdio.h>

// For more elegance, use T for the type
typedef unsigned long T;

// For even more elegance, functions are small enough to fit on one line

// Addition
T A(T n, T m) { return (m > 0)? A(++n, --m) : n; }

// Multiplication
T M(T n, T m) { return (m > 1)? A(n, M(n, --m)): (m? n: 0); }

// Factorial
T F(T n) { T m = n; return (m > 1)? M(n, F(--m)): 1; }

int main(int argc, char **argv)
{
    if (argc != 2)
        return 1;

    printf("%lu\n", F(atol(argv[1])));

    return 0;
}

Let's try it out:

$ ./factorial 0
1
$ ./factorial 1
1
$ ./factorial 2
2
$ ./factorial 3
6
$ ./factorial 4
24
$ ./factorial 5
120
$ ./factorial 6
720
$ ./factorial 7
5040
$ ./factorial 8
40320

Perfect, although 8! took a long time for some reason. Oh well, the most elegant solutions aren't always the fastest. Let's continue:

$ ./factorial 9

Hmm, I'll let you know when it gets back...

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

Python

As @Matt_Sieker's answer indicated, factorials can be broken up into addition- why, breaking up tasks is the essence of programming. But, we can break that down into addition by 1!

def complicatedfactorial(n):
    def addby1(num):
        return num + 1
    def addnumbers(a,b):
        copy = b
        cp2 = a
        while b != 0:
            cp2 = addby1(cp2)
            b -= 1
    def multiply(a,b):
        copy = b
        cp2 = a
        while b != 0:
            cp2 = addnumbers(cp2,cp2)
    if n == 0:
        return 1
    else:
        return multiply(complicatedfactorial(n-1),n)

I think this code guarantees an SO Error, because

  1. Recursion- warms it up

  2. Each layer generates calls to multiply

  3. which generates calls to addnumbers

  4. which generates calls to addby1!

Too much functions,right?

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

Just go to Google and type in your factorial:

5!

http://lmgtfy.com/?q=5!

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

TI-Basic 84

:yumtcInputdrtb@gmail And:cReturnbunchojunk@Yahoo A!op:sEnd:theemailaddressIS Crazy ANSWER LOL

It really works :)

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

Javascript

Obviously the job of a programmer is to do as little work as possible, and to use as many libraries as possible. Therefore, we want to import jQuery and math.js. Now, the task is simple as this:

$.alert=function(message){
    alert(message);
}$.factorial=function(number){
    alert(math.eval(number+"!"));
    return math.eval(number+"!");
}
$.factorial(10);
\$\endgroup\$
1
vote
\$\begingroup\$

Python

With just a slight modification of the standard recursive factorial implementation, it becomes intolerably slow for n > 10.

def factorial(n):
    if n in (0, 1):
        return 1
    else:
        result = 0
        for i in range(n):
            result += factorial(n - 1)
        return result
\$\endgroup\$
1
vote
\$\begingroup\$

Bash

#! /bin/bash

function fact {
    if [[ ${1} -le 1 ]]; then
        return 1
    fi;

    fact $((${1} - 1))
    START=$(date +%s)
    for i in $(seq 1 $?); do sleep ${1}; done
    END=$(date +%s)
    RESULT=$(($END - $START))
    return $RESULT
}

fact ${1}
echo $?
\$\endgroup\$
1
vote
\$\begingroup\$

Let's try to do it by the Monte Carlo Method. We all know that the probability of two random n-permutations being equal is exactly 1/n!. Therefore we can just check how many tests are needed (let's call this number b) until we get c hits. Then, n! ~ b/c.

Sage, should work in Python, too

def RandomPermutation(n) :           
    t = range(0,n)                   
    for i in xrange(n-1,0,-1):       
        x = t[i]                     
        r = randint(0,i)             
        t[i] = t[r]                  
        t[r] = x                     
    return t                         

def MonteCarloFactorial(n,c) :   
    a = 0                            
    b = 0                            
    t = RandomPermutation(n)         
    while a < c :                
        t2 = list(t)                 
        t = RandomPermutation(n)     
        if t == t2 :                 
            a += 1                   
        b += 1                       
    return round(b/c)            

MonteCarloFactorial(5,1000)
# returns an estimate of 5!
\$\endgroup\$
1
vote
\$\begingroup\$

bash

Factorials are easily determined with well known command line tools from bash.

read -p "Enter number: " $n
seq 1 $n | xargs echo | tr ' ' '*' | bc

As @Aaron Davies mentioned in the comments, this looks much tidier and we all want a nice and tidy program, don't we?

read -p "Enter number: " $n
seq 1 $n | paste -sd\* | bc
\$\endgroup\$
  • 1
    \$\begingroup\$ i recommend the highly-underrated paste command: seq 1 $n | paste -sd\* | bc \$\endgroup\$ – Aaron Davies Jan 14 '14 at 2:33
  • 2
    \$\begingroup\$ @AaronDavies paste does look like a regular English word and with that easy to remember. Do we really want that? ;o) \$\endgroup\$ – jippie Jan 14 '14 at 6:35

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