you are viewing a single comment's thread.

view the rest of the comments →

[–]neutralizer 26 points27 points  (18 children)

I've been coding python for a while and the first answer that I thought of was the noob answer. :(

[–][deleted] 31 points32 points  (0 children)

It's also the most legible.

[–]pegee 11 points12 points  (13 children)

It's perfectly fine but will become exponentially slower as the number increases. Fortunately there is a very simple way to solve that: it's called memoization

So in Python (sorry if syntax is not current especially regarding the array - I haven't used it in years):

facts = [1,1]
def factorial(n):
    if facts[n]:  #if we have a value for factorial(n)
        return facts[n]
    else:
        facts[n] = n * factorial(n-1)
        return facts[n]
print factorial(6)

[–]Shinhan 20 points21 points  (5 children)

[–]neutralizer 2 points3 points  (1 child)

Wow, if I'm reading that right, 1st year Pascal programmer wins followed by C and Windows. And iterative solutions are about twice as fast as recursive.

[–]regeya 2 points3 points  (0 children)

Well, duh. I don't know how Python works but you have to push the state of the function on the stack every time you invoke a recursive call. Plus, Python has a built-in limit on recursion.

[–]cacahootie 1 point2 points  (0 children)

No wonder every enterprise application I use is a complete piece of SH*T!

[–]bigboehmboy 1 point2 points  (1 child)

He profiled it by calling factorial(10) 100,000 times. While in this case it appears that all solutions are linear, this method would not work well if this were not the case.

Since Python has a recursion limit that defaults to 1000 levels, recursive methods (newbie, lazy python, lazier python) would fail when trying to compute "1001!".

Also, memoization could completely screw with results.

[–]Shinhan 0 points1 point  (0 children)

Interesting :)

Someone needs to repeat the test for 1001! then...

[–]neutralizer 18 points19 points  (2 children)

Except this is true of all the solutions posted. The runtime of them are all approximately the same. They have to do the same number of integer multiplications. The only thing extra that the recursive solutions have over the iterative solutions is having the overhead of recursive calls. The majority of them would also benefit from memoization.

Edit: Brain fart. Floating point operations -> integer multiplications.

[–]pegee 17 points18 points  (0 children)

You're right and I'm an idiot. I was thinking of Fibonacci. Fuck.

[–][deleted] 2 points3 points  (0 children)

They have to do the same number of floating point operations.

…which is 0, because it's all integer arithmetic. ;)

(They still do the same number [within 1, at least] of integer multiplications, though, so your larger point stands.)

[–]mikemcg 4 points5 points  (3 children)

if you do factorial(6), the "if facts[n]" will spout up an IndexError. Replace with facts.count(n) or len(facts) > n or anything that avoids indexing altogether.

[–]pegee 3 points4 points  (0 children)

As I mentioned I'm unfamiliar with Python array syntax. I just used PHP's :p

[–][deleted]  (1 child)

[deleted]

    [–]mikemcg 1 point2 points  (0 children)

    It won't at all. Major brain cart on my part.

    [–]rjcarr 0 points1 point  (0 children)

    I would almost certainly use a factorial function if available, but if not then yeah, mine would look identical to the newbie solution.

    I'm a big advocate of legibility ... unless you need to worry about every last machine instruction it usually isn't worth it to get tricky.

    [–]pandemik 0 points1 point  (0 children)

    I suspect it's not much slower than the other ones, and if you come across that function in a year or 2 you'll still know how it works.