Trying without factorial() in factorial()


#1

hi, im trying wothout factorial in factorial, my code looks like this:
i dont know what am i doing wrong, if someone could help me plz :slight_smile:

def factorial(x):
    lista=[]
    i=0
    total=1
    while i<x:
        lista.append(x-i)
        i+=1
    print lista

    for i in lista:
        total*=i
    
print factorial(3)

5. Factorial, how does hint solution work?
#2

Assuming the indentation is correct, let's look at what your code appears to do.

lista = []
i = 0
total = 1

A list, a counter, and a unity factor initialized. Now let's see how they play out.

while i < x:
    lista.append(x-i)
    i += 1

We now have a list (a sequence, actually) of numbers from 1 to x.

for i in lista:
    total *= i

The above iterates the list and augments a sequential product.

All that remains is to return the product, the one line missing from the OP code.

return total

Ultimately this is good code because it has been thought out, and follows a logical step by step approach, and there are no errors, most important. Well done,@netace54312.

Now that you have come this far, no doubt you are looking at ways to simplify your code (don't we all, though?). How can we make this code simpler, and faster? Let's start by looking at what we can reduce.

lista = []
i = 0
while i < x:
    # loop code

can all be replaced with one line:

lista = range(2, x + 1)

So now the program looks like this:

total = 1
lista = range(x + 1)
for i in lista:
    total *= i
return total

I set the range lower bound to 2 because total makes up the 1. The list will be,

[2, 3, 4, .., x]

Remember, a range never includes the upper bound.

How do we reduce this some more?

total = 1
for i in lista:
    # loop code
return total

All can be replaced with this...

return reduce(lambda a, b: a * b, lista)

which gives us this program:

def factorial(x):
    lista = range(2, x + 1)
    return reduce(lambda a, b: a * b, lista)

Having reached this point we could ask, "do we really need the variable?" Answer: No, we do not need it. We can write a pure function with no extraneous variables.

def factorial(x):
    return reduce(lambda a, b: a * b, range(2, x + 1))

We have completely refactored your original code. This is not a show of prowess. We did this from your code.

Lastly, since there are no negative factorials, by definition, we need one more validation feature.

def factorial(x):
    return reduce(lambda a, b: a * b, range(2, abs(x) + 1))

I shouldn't have said, 'lastly' because we still have to be sure that x is a number, and an integer at that.

def factorial(x):
    try: return reduce(lambda a, b: a * b, range(2, int(abs(x)) + 1))
    except: return False

or with more expllicit exceptions,

import sys
def factorial(x):
    try: return reduce(lambda a, b: a * b, range(2, int(abs(x)) + 1))
    except: print "Unexpected error:", sys.exc_info()[0]
    raise

#3

thanks (again) a lot!!!
ure awesome :slight_smile:


#4

If this were in a real world program, it would be better to just use this code:
from math import factorial
Correct?


#5

Real world, yes. But how does one learn to write that program without first trying to?


#7