I'm building a tool to output how many time the code run in python. For instance, when the input is
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
The output would be
def fib(n): 21891
if n <= 1: 10946
return n 10946
return fib(n-1) + fib(n-2) 8000
fib(20) 1
The number on the right shows how many time the code run.
What I doing is rewriting the function to
def fib(n):
dic["count_0"] += 1
if n <= 1:
dic["count_6"] += 1
return n
dic["count_7"] += 1
return fib(n-1) + fib(n-2)
dic["count_8"] += 1
fib(20)
dic["count_10"] += 1
Then handle the edge case like comments or return keyword. I wonder any other way to do this without to many hacks like this.
Related
I am trying to perform a Collatz algorithm on the following code. It works fine when I use a range of 1-10 etc... However, if the range is for example 1-500,000 it's too slow and won't ever show me the output of the longest sequence.
numberArray = []
s=int(1)
f=int(10)
def collatz(n):
global count
if n == 1:
count += 1
numberArray.append(count)
return True
elif (n % 2) == 0:
count += 1
collatz(n/2)
else:
count += 1
collatz(3*n+1)
for i in range (s, f+1):
count = 0
ourNumber = i
collatz(i)
print(max(numberArray))
Stef means something like this, which uses a dictionary to memorise the values that have already been counted:
s = 1
f = 10000000
def collatz(n):
if n in collatz.memory:
return collatz.memory[n]
if (n % 2) == 0:
count = collatz(n//2)+1
else:
count = collatz((3*n+1)//2)+2
collatz.memory[n] = count
return count
collatz.memory = {1:0}
highest = max(collatz(i) for i in range(s, f+1))
highest_n = max(collatz.memory, key=collatz.memory.get)
print(f"collatz({highest_n}) is {highest}")
Output:
collatz(8400511) is 685
Use lru_cache decorator. Its function to memorize (cache) the returned value of function called with specific argument.
Also read how to write clean code in python
The next code solves your problem
from functools import lru_cache
number_array = []
s = 1
f = 500000
#lru_cache
def collatz(n: int):
if n == 1:
return 1
elif n % 2 == 0:
return 1 + collatz(n // 2)
else:
return 1 + collatz(3 * n + 1)
for i in range(s, f + 1):
number_array.append(collatz(i))
print(number_array)
Suppose we have the following recursion formula
I wrote the following code based on that recursion,
def f(k):
if(k <= 2):
return k
elif(k % 2 ==0):
return 5*f(k/2) + 1
else:
return f((k-1)/2) + 2
Is there a way to make this implementation faster and more efficient?
something like this
storage = dict()
def f(k):
if(k <= 2):
return k
elif k in storage:
return storage[k]
elif(k % 2 ==0):
storage[k] = 5*f(k/2) + 1
return storage[k]
else:
storage[k] = f((k-1)/2) + 2
return storage[k]
You should use integer divisions because results will always be integers. Also, you don't need the parentheses around conditions.
There is a decorator in the functools module to automatically cache (memoize) your function:
from functools import lru_cache
#lru_cache()
def f(k):
if k <= 2:
return k
elif k % 2 == 0:
return 5 * f(k//2) + 1
else:
return f((k-1)//2) + 2
Note that this function converges extremely rapidly (exponentially?). The cache may not improve it much.
I've written a code block to find n-th prime number.
For instance if n=2, then the result is 3 and if n=3, then 5 and so on.
Below is my code.
def prime_or_not(n):
for i in range(2, int(n ** 0.5)+1):
if n % i == 0:
return False
else:
return True
def get_first_n_prime(n):
while True:
if prime_or_not(n):
yield n
n += 1
def get_nth_prime_number(n, initial_number=2):
count = 0
for next_prime in get_first_n_prime(initial_number):
count += 1
if count < n:
continue
else:
return next_prime
With the code above, I could get expected result.
The question, however, is that I'm not sure whether this is pythonic way of using generator (with yield in a function). Any feedback or comment would be immensely helpful.
def fib(n):
if n == 1 or n == 2:
return 1
return fib(n-1) + fib(n-2)
for i in range(5):
print(fib(i))
I want to print first 5 result of Fibonacci sequence only to get
RecursionError: maximum recursion depth exceeded in comparison
I think there is an exit of every positive n and print(fib(4)), print(fib(20)) and print(fib(100)) works perfectly.
What's wrong with my code?
range(5) starts at 0 and since you are not checking for 0 in your function, the recursion never ends.
As a sidenote, you are not calculating the fibonacci sequence correctly, you should add up
fib(n-1) + fib(n-2)
Try this:
def fib(n):
if n <= 2:
return n
return fib(n-1) + fib(n-2)
A generally better approach at calculating the n-th fibonacci number is to use a loop, since you end up calculating the same values over and over again if you use recursion. Using a loop you can do it like this:
def fibonacci(n):
if n < 2:
return 1
a = 1
fib = 1
for i in range(n-2):
a, fib = fib, a + fib
return fib
there is an exit of every positive n.
Yes, there is. But how about fib(0)?
Try print(list(range(5)))
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