Calculating factorials with Python - python

EDIT: I know I can import factorials but I'm doing this as an exercise
Trying to get the factor of a given number with a function in Python.
For example:
factorial(4) = 4 * 3 * 2 * 1 = 24
def factorial(x):
n = x
while n >= 0:
x = n * (n - 1)
n -= 1
return x

try like this: to make your code work
def factorial(x):
n = 1 # this will store the factorial value
while x > 0:
n = n*x
x -= 1
return n
you got many advice on comments follow it

A good way of approaching this would be using recursion where a function calls itself. See Function for Factorial in Python
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
But in your case your return statement actually breaks out of the while loop. So if you pass in 5 you get 20 back which is obviously not 5! (5 factorial).
Instead, try this:
def factorial(x):
n = 1
while x > 1:
n *= x
x -= 1
return n
print (factorial(5))
But do have a go at the recursive approach.
If you really want to cheat try:
import math
math.factorial(n)

I present an even shorter code for recursive factorial calculation. Not sure if it is faster or slower than other approaches:
def fac(n):
return 1 if n==1 else n*fac(n-1)
fac(10)
3628800

def factorial(n):
total = 1
for num in range(2,n+1):
total *= num
return total

input:
n = 10
print(str(n) + "! = ", end = '')
def factorial(n):
'''
print factorial number in human way
'''
if n < 0:
return 'factorial() not defined for negative values'
if n == 0:
return 1
if n == 1:
print('', n, ' =', end = ' ')
return 1
else:
print('', n, '*', end = '')
return n * factorial(n - 1)
print(factorial(n))
output:
10! = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 3628800

Related

python Find the sum of all multiples of n below m

Find the sum of all multiples of n below m
Keep in Mind n and m are natural numbers (positive integers) m is
excluded from the multiples
sumMul(2, 9) ==> 2 + 4 + 6 + 8 = 20
sumMul(3, 13) ==> 3 + 6 + 9 + 12 = 30
sumMul(4, -7) ==> "INVALID"
I did sum of list using range(n, m, n) using n as step.
I also tried modulus to avoid range 3 args error.
I can pass many tests but cannot pass all of them.
I have tried lots of logic but to no avail. What I am doing wrong?
CODEWARS: https://www.codewars.com/kata/57241e0f440cd279b5000829/train/python
MY CODE:
def sum_mul(n, m):
my_list = [number for number in range(n, m) if number % n == 0]
sum_list = sum(my_list)
if sum_list >= 1:
return sum_list
elif n == 0 and m == 0:
return 'INVALID'
elif n == m:
return n - m
elif n > m:
return 'INVALID'
Your code fails if n == 0 as then the number % n checks in the list comprehension fail, so you should check that before trying to compute the sum. Also, you could use a range with step and just do sum(range(n, m, n)). However, both ways might be too slow for some test cases with very large m.
You can do this in O(1) with the following observations:
there are (m-1) // n multiples of n below m
the sum of natural numbers from 1 to n is n*(n+1)//2
Combine those two to get the result.
Example for sumMul(3, 13) ==> 3 + 6 + 9 + 12 = 30:
(13-1) // 3 == 4 so we know there are 4 multiples of 3 below 13
those are 3 + 6 + 9 + 12 == 3 * (1 + 2 + 3 + 4)
with (2) we know 1 + 2 + 3 + 4 == 4*5//2 == 10
so the result is 10 * 3 == 30
Putting that into code and handling the special cases is left as an exercise to the interested reader.
You have one main problem, that is you should prevent the situation when n==0 and you divide it in your list comprehension. It will raise zero division error. so you should check before the validation that n is not equal to zero.
Second thing is that you need to check whether n or m are negatives, as the exercise declared both n and m should be positives.
def sum_mul(n, m):
if n==0:
return 'INVALID'
my_list = [number for number in range(n, m) if number % n == 0]
sum_list = sum(my_list)
if sum_list >= 1:
return sum_list
elif n < 0 and m <= 0:
return 'INVALID'
elif n == m:
return n - m
elif n > m:
return 'INVALID'
You can just compute that result mathematically using integer divisions:
def sum_mul(n, m):
if n<1 or n>m: return "INVALID"
return m//n*(m//n+1)//2*n
First you get the number of multiple of n in m (which is merely dividing m by n ignoring the remainder) : m//n
Multiples of n will be nx1, nx2, nx3, ... up to the number of multiples. Factorizing the sum of those by n we get: n(1+2+3+ ... m//n).
The sum of numbers from 1 up to a given number x is obtained by x(x+1)/2. In this case x is the number of multiples m//n
Putting it all together we get n * x * (x+1) /2 where x is m//n, so:
n * (m//n) * (m // n + 1) // 2
You should comprove all cases before call sum function.
Like this:
def sum_mul(n, m):
if n == 0 or m == 0:
return 'INVALID'
if n == m:
return n - m
if n<0 or m<0:
return 'INVALID'
my_list = [number for number in range(n, m) if number % n == 0]
return sum(my_list)
In fact, you dont't need to create if elif structure because you are using returns, so next instruction after return not executed.

Function doesn't return anything after giving a big number as an argument

I'm learning Python by doing Project Euler questions and am stuck on Problem #3.
I think I've found a solution that works, but when inserting the large number 600851475143 it just doesn't return anything. I believe that it just loads and loads cause even with 6008514 it takes 10 secs to return the answer.
# What is the largest prime factor of the number x?
import math
def isPrime(x):
try:
sqr = math.sqrt(x)
if x == 0 or x == 1:
return 0
for n in range (2 , int(sqr)+1):
if x % n == 0:
return 0
return 1
except:
return 'Give positive numbers.'
def largestPrimeFactor(x):
if isPrime(x) == 1:
return 'This number is prime.'
else:
largest = -1
mid = x/2
for n in range(2,int(mid)+1):
if isPrime(n):
if x % n == 0:
largest = n
if largest == -1:
return 'Enter numbers above 1.'
else:
return largest
print(largestPrimeFactor(600851475143))
This code should work:
import math
def isPrime(x):
try:
sqr = math.sqrt(x)
if x == 0 or x == 1:
return 0
n = 2
highest = x
while n < highest:
if x%n ==0:
return 0
highest = x/ n
n +=1
return 1
except:
return 'Give positive numbers.'
def largestPrimeFactor(x):
if isPrime(x) == 1:
return 'This number is prime.'
n = 2
highest = x
largest = 1
while n < highest:
if x%n == 0:
if isPrime(n):
largest = n
highest = x/n
n +=1
return largest
print(largestPrimeFactor(600851475143))
I made an optimization:
you check if every number is a factor of x while if for example 2 is not a factor of x for sure the maximum factor of x can be x/2. Hence if n is not a factor of x the maximum possible factor of x can just be x/n.
The code for large numbers just takes really long time, as pointed out by comments. I report other bugs.
Bug 1. Inappropriate use of try/except clause. It is recommended that try contains a single command and except catches the error. PEP8 also recommends specifying the type of error. Moreover, for your function, the error is never raised.
Bug 2. Redundancy. If x is not prime, you call isPrime for each value (let's call it i) from 2 to x/2. isPrime cycles for each number from 2 to sqrt(i). Therefore, isPrime(i) takes O(sqrt(i)) time, and we call it for i from 2 to x/2. Roughly, its running time is about O(x^(3/2)). Even if don't know a more optimal approach, this approach asks for memoization.
i have another way:
def Largest_Prime_Factor(n):
prime_factor = 1
i = 2
while i <= n / i:
if n % i == 0:
prime_factor = i
n /= i
else:
i += 1
if prime_factor < n:
prime_factor = n
return prime_factor
it faster than previous
try it:
import math
def maxPrimeFactors (n):
maxPrime = -1
while n % 2 == 0:
maxPrime = 2
n >>= 1
for i in range(3, int(math.sqrt(n)) + 1, 2):
while n % i == 0:
maxPrime = i
n = n / i
if n > 2:
maxPrime = n
return int(maxPrime)
n = 600851475143
print(maxPrimeFactors(n))

How to write 2**n - 1 as a recursive function?

I need a function that takes n and returns 2n - 1 . It sounds simple enough, but the function has to be recursive. So far I have just 2n:
def required_steps(n):
if n == 0:
return 1
return 2 * req_steps(n-1)
The exercise states: "You can assume that the parameter n is always a positive integer and greater than 0"
2**n -1 is also 1+2+4+...+2n-1 which can made into a single recursive function (without the second one to subtract 1 from the power of 2).
Hint: 1+2*(1+2*(...))
Solution below, don't look if you want to try the hint first.
This works if n is guaranteed to be greater than zero (as was actually promised in the problem statement):
def required_steps(n):
if n == 1: # changed because we need one less going down
return 1
return 1 + 2 * required_steps(n-1)
A more robust version would handle zero and negative values too:
def required_steps(n):
if n < 0:
raise ValueError("n must be non-negative")
if n == 0:
return 0
return 1 + 2 * required_steps(n-1)
(Adding a check for non-integers is left as an exercise.)
To solve a problem with a recursive approach you would have to find out how you can define the function with a given input in terms of the same function with a different input. In this case, since f(n) = 2 * f(n - 1) + 1, you can do:
def required_steps(n):
return n and 2 * required_steps(n - 1) + 1
so that:
for i in range(5):
print(required_steps(i))
outputs:
0
1
3
7
15
You can extract the really recursive part to another function
def f(n):
return required_steps(n) - 1
Or you can set a flag and define just when to subtract
def required_steps(n, sub=True):
if n == 0: return 1
return 2 * required_steps(n-1, False) - sub
>>> print(required_steps(10))
1023
Using an additional parameter for the result, r -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r * 2)
for x in range(6):
print(f"f({x}) = {required_steps(x)}")
# f(0) = 0
# f(1) = 1
# f(2) = 3
# f(3) = 7
# f(4) = 15
# f(5) = 31
You can also write it using bitwise left shift, << -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r << 1)
The output is the same
Have a placeholder to remember original value of n and then for the very first step i.e. n == N, return 2^n-1
n = 10
# constant to hold initial value of n
N = n
def required_steps(n, N):
if n == 0:
return 1
elif n == N:
return 2 * required_steps(n-1, N) - 1
return 2 * required_steps(n-1, N)
required_steps(n, N)
One way to get the offset of "-1" is to apply it in the return from the first function call using an argument with a default value, then explicitly set the offset argument to zero during the recursive calls.
def required_steps(n, offset = -1):
if n == 0:
return 1
return offset + 2 * required_steps(n-1,0)
On top of all the awesome answers given earlier, below will show its implementation with inner functions.
def outer(n):
k=n
def p(n):
if n==1:
return 2
if n==k:
return 2*p(n-1)-1
return 2*p(n-1)
return p(n)
n=5
print(outer(n))
Basically, it is assigning a global value of n to k and recursing through it with appropriate comparisons.

Sum of range(1,n,2) values using recursion

I'm trying to translate a loop to a recursive algorithm. Fairly simple, I've just hadn't been able to make it ignore the n value when summing up the values, like range does.
This is the iterative function:
def function(n):
total=0
for i in range(1,n,2):
total += i
print(total)
function(5) # Output: 4
This is the recursive I've tried:
def function1(n):
if n==1:
return n
else:
return n+function1(n-2)
function(5) # Output: 9
So function1 does sum the n when it should be ignored. Cause range() does not include the stop number.
Then, I tried:
def f1(n):
def f_recursive(n):
if n==1 or n==2:
return 1
elif n==0:
return 0
else:
return n + f_recursive(n - 2)
return f_recursive(n) - n
print(f1(5)) # Output: 4 Yeiii!!
But then I realised, that only works for odd numbers. Not for even. If f1(6) then you get 4 when it should be 9, because it ends up being 11-6= 9.
So silly me I tried:
def f1(n):
def f_recursive(n):
if n==1 or n==2:
return 1
elif n==0:
return 0
elif n%2 == 0:
return n + f_recursive(n - 3)
elif n%2 == 1:
return n + f_recursive(n - 2)
return f_recursive(n) - n
print(f1(6))
Which of course also did not work. Am I not understanding recursion properly here?
The tricky part is excluding the upper bound. If the upper bound is your only parameter n, you have to know when it's the first call, and when it's an intermediate (recursive) call. Alternatively, if inner functions are okay, you could instead just count from 1 up until you hit n:
def function1(n):
def inner(i):
return 0 if i >= n else i + inner(i + 2)
return inner(1)
You want to compute the sum of all odd integers from 1 up to, but not including, n.
This leaves 2 possibilities:
If n is <= 1, there are no numbers to sum, so the sum is 0.
The highest number that might be included in the list is n-1, but only if it is odd. Either way, the rest of the sum is "the sum of all odd integers from 1 up to, but not including, n-1" (sound familiar?)
This translates to:
def f1(n):
if n <= 1:
return 0
else:
isOdd = (n-1)%2==1
return f1(n-1) + (n-1 if isOdd else 0)
The problem with your recursion is that you're returning n rather than the value in the range (list) that you're currently on, this poses a problem since n is not inclusive within the range and should not be added to the final total
Ideally you need to reverse the logic and traverse it the same way your range does
def func(start,end, step):
if(start >= end):
return 0
return start + func(start + step, end, step)
You just have to recognize the three types of ranges you might be adding up.
range(1, n, 2) where n <= 1: The empty range, so the sum is 0
range(1, n, 2) where n > 1 and n is even: the range is 1, ..., n-1. (E.g. range(1, 6, 2) == [1, 3, 5])
range(1, n, 2) where n > 1 and n is odd: the range is 1, ..., n-2 (E.g., range(1, 5, 2) == [1, 3]
Translating this to code is straightforward:
def f_recursive1(n):
if n <= 1:
return 0
elif n % 2 == 0:
return n - 1 + f_recursive1(n-2)
else: # n odd
return n - 2 + f_recursive1(n-2)
However, this does more work than is strictly necessary, since subtracting 2 from n will never change its parity; you don't need to check n is even or odd in every recursive call.
def f_recursive2(n):
def f_helper(x):
if x <= 0:
return 0
return x + f_helper(x-2)
if n % 2 == 0:
return f_helper(n-1)
else:
return f_helper(n-2)
If we are allowed multiplication and division, I hope you realise that this particular task does not require more than just a base case.
Python code:
def f(n):
total=0
for i in range(1,n,2):
total += i
return total
def g(n):
half = n // 2
return half * half
for n in xrange(100):
print f(n), g(n)
Since
*
* * *
* * * * *
* * * * * * *
can be seen as nested, folded rows. Here are the top two folded rows:
*
* * *
* * * *
* * * *
Let's rotate counterclockwise 45 degrees
* * * *
* * * *
* *
* *
and add the other two folded rows,
*
* *
* * * *
* * * *
* * * *
* * *
and
*
to get
* * * *
* * * *
* * * *
* * * *
the area of a square.

Why does a change in multiplication sign in factorial to addition sign give such an output?

Question: Why is the output 11 not 12?
i+4+i+3+i+2 = 1+4+1+3+1+2 = 12
Code:
def factorial(n):
i = 1
while n >= 1:
#I changed the signs from * to + after getting the factorial from * method.
i = i * n --> i = i + n
n = n - 1
return i
print factorial(4)
11
To get expected i+4 + i+3 + i+2 and result 12 you need
def factorial(n):
result = 0
i = 1
while n > 1:
result += i + n
n = n - 1
return result
print(factorial(4))
I add to new variable result so I don't change i and it is 1 all the time.
I also use > instead of >= so it ends after i+2 and it doesn't add i+1
def factorial(n):
i = 1
while n >= 1:
#I changed the signs from * to + after getting the factorial from * method.
print(i)
i = i + n
n = n - 1
return i
print(factorial(4))
If you print i, you will find i has changed after first loop.
So the output should be 1+4+3+2+1=11
(Posted on behalf of the question author).
Tips from me to solve the problem: 1. understand the concept of loop 2. try to print the answer on your own - i=5, n=3, i=8, n=2, i=10, n=1, i=11

Categories

Resources