I'm iterating 4 million times (for a project). This is taking forever to do. I was wondering how I can go faster.
numbers = [0,1]
evenNumbers = []
y = 0
l = 0
for x in range (1,4000000):
l = numbers[x-1] + numbers[x]
numbers.append(l)
for k in numbers:
if k % 2 ==0:
evenNumbers.append(k)
for n in evenNumbers:
y += n
print(y)
This is going to be very slow regardless due to the how big the numbers are getting, but you can speed it up significantly by just not storing all the intermediate values:
m, n = 0, 1
y = 0
for _ in range(1, 4000000):
m, n = n, m + n
if n % 2 == 0:
y += n
print(y)
You should just compare the time it takes for each function here to complete, as they are the three different ways that most would approach iteration.
import time
def foreach(arr):
for i in range(len(arr)):
print(arr[i])
def forin(arr):
for i in arr:
print(i)
def whileloop(arr):
i = 0
while i < len(arr):
print(arr[i])
i += 1
def main():
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
start = time.time()
foreach(arr)
end = time.time()
print("foreach: ", end - start)
start = time.time()
forin(arr)
end = time.time()
print("forin: ", end - start)
start = time.time()
whileloop(arr)
end = time.time()
print("whileloop: ", end - start)
if __name__ == "__main__":
main()
Related
def encryption(n):
if len(n) == 2:
return n
result = []
for i in range(len(n) - 1):
total = n[i] + n[i + 1]
right_most_digit = total % 10
result.append(right_most_digit)
if len(result) > 2:
result = encryption(result)
return "".join([str(x) for x in result])
if __name__ == '__main__':
numbers = [1, 5, 7, 9]
print(encryption(numbers))
I need help with this code.
The problem is to add the two adjacent numbers and keep the right_most_digit, repeat the process to a point where only two numbers left, and return a string.
For example, 1+5, 5+7, 7+9 will be 6,2,6, then 6+2, 2+6 will be 8,8, then return 88 as a string.
With the least changes,
def encryption(n):
if len(n) == 2:
return n
result = []
for i in range(len(n) - 1):
total = n[i] + n[i + 1]
right_most_digit = total % 10
result.append(right_most_digit)
if len(result) > 2:
result = encryption(result)
return result
if __name__ == '__main__':
numbers = [1, 5, 7, 9]
print("".join([str(x) for x in encryption(numbers)]))
print("".join([str(x) for x in encryption(numbers)]).lstrip("0")) if you also want to strip any leading 0
Since you asked about a different approach, you might consider not doing this recursively. You can simply keep processing the list in a while loop until the list is of length 2 or less. Then convert to a string:
def encryption(n):
while len(n) > 2:
n = [(a + b) % 10 for a, b in zip(n, n[1:])]
return "".join([str(x) for x in n])
numbers = [1, 5, 7, 9]
print(encryption(numbers))
# 88
This is a little easier to reason about and it also makes it easy to debug by sticking a print(n) in the loops to see the progression.
Doing this for school project.
I need to:
Execution of execution time measurements for given algorithms:
a. Measurements should be made for random sets of n = 100,
1000, 10000, 100000, 300000
b. For every n, sort should be looped 100 times and on
the end of the measurement results are averaged:
Draw a new set of numbers to sort by quantity
elements n. The range of random numbers 0 - 10000.
Get T1 time.
Perform a sort of a randomly selected set.
Get T2 time.
Carry out a subtraction of the time T2 - T1 and save the result on
set of measurements
Is there any good way to speed up processing of that code?
import time
# bubble_sort
def bubble_sort(array):
for iter_num in range(len(array) - 1, 0, -1):
for idx in range(iter_num):
if array[idx] > array[idx + 1]:
temp = array[idx]
array[idx] = array[idx + 1]
array[idx + 1] = temp
def timing(func, b):
timingList = list()
for x in range(100):
array = [randint(0, 10000) for i in range(b)]
time1 = time.time()
func(array)
time2 = time.time()
timingList.append(time2 - time1)
return (sum(timingList) / len(timingList)) * 1000
def imlazy(func):
print(timing(func, 100))
print(timing(func, 1000))
print(timing(func, 10000))
print(timing(func, 100000))
print(timing(func, 300000))
if __name__ == '__main__':
print(imlazy(bubble_sort))
Notwithstanding the general awfulness of the bubble sort, here's a slightly more efficient implementation:-
def bubble_sort(L):
e = len(L)
while e > 1:
es = 0
for i in range(e-1):
if L[i] > L[i+1]:
L[i], L[i+1] = L[i+1], L[i]
es = i+1
e = es
I recently started to learn python and i'm using CodeWars to train. The task is to return a list [p, p + 4, p + 6, p + 10, p + 12, p + 16] where all of them are primes. The sum of them should be higher than sum_limit. For low values it is working, but at high values (about 2 million) the runtime is high. How can I reduce the runtime?
from math import sqrt; from itertools import count, islice
def find_primes_sextuplet(sum_limit):
for x in range(sum_limit):
if isPrime(x) and isPrime(x+4) and isPrime(x+6) and isPrime(x+10) and isPrime(x+12) and isPrime(x+16):
possible = [x, x+4, x+6, x+10, x+12, x+16]
if sum(possible) > sum_limit:
return possible
def isPrime(n):
return n > 1 and all(n%i for i in islice(count(2), int(sqrt(n)-1)))
print(find_primes_sextuplet(2000000))
For non-negative integer values of n, you can use this:
def isPrime(n):
if n == 1 or n % 2 == 0 or n % 3 == 0:
return False
end = int(sqrt(n)+1)
for start in [5, 7]:
for k in range(start, end, 6):
if n % k == 0:
return False
return True
It won't change the theoretical complexity, but it will reduce the practical running-time.
And if you change the outer loop to for x in range(5, sum_limit), then you can also get rid of the initial check if n == 1 or n % 2 == 0 or n % 3 == 0.
Here's my thinking about reducing complexity and run time.
You can write a sieve in O(n log log n). Here's a reasonable implementation:
def sieve(n):
grid = [None for _ in range(n+1)]
i = 2
while i < n+1:
if grid[i] is None:
grid[i] = True
for p in range(2*i, n+1, i):
grid[p] = False
else:
i += 1
return (index for index, b in enumerate(grid) if b)
There are 6 numbers, and the total amount added to the first number is 48. So the minimum possible value for the first number is (n - 48) / 6. In my sieve we can iterate the generator until number is greater than that.
def get_remaining_sieve(n):
g = sieve(n)
current = next(g)
min_value = (n - 48) / 6
while current < min_value:
current = next(g)
return [current] + list(g)
Now just iterate through every slice of length 6, and check if the separation matches the desired separation (4, 2, 4, 2, 4).
remaining = get_remaining_sieve(n)
for start in range(len(remaining) - 5):
slice = remaining[start:start+6]
differences = [slice[j] - slice[j-1] for j in range(1, 6)]
if differences == [4, 2, 4, 2, 4]:
print(slice)
Summary
Based on those principles, I've come up with this solution:
from itertools import dropwhile, islice
def get_solutions(n):
grid = [None for _ in range(n+1)]
i = 2
while i < n+1:
if grid[i] is None:
grid[i] = True
for p in range(2*i, n+1, i):
grid[p] = False
else:
i += 1
sieve = (index for index, b in enumerate(grid) if b)
min_value = (n - 48) / 6
reduced_sieve = dropwhile(lambda v: v < min_value, sieve)
reference_slice = list(islice(reduced_sieve, 6))
while True:
try:
ref = reference_slice[0]
differences = [v - ref for v in reference_slice[1:]]
if differences == [4, 6, 10, 12, 16]:
yield reference_slice
reference_slice = reference_slice[1:] + [next(reduced_sieve)]
except StopIteration:
break
n = 2000000
print(next(get_solutions(n))) # 695ms
# or for all solutions
for solution in get_solutions(n): # 755ms
print(solution)
This runs in less than a second on my computer.
There are various ways to improve the runtime of your code. For example a lot of numbers are checked for being prime numbers even though their sum is not eligible as a result. Calculating the sum of 6 numbers is faster than checking if they are prime. You could move the sum check above the prime check and only check the numbers for primes if their sum would be eligible.
To improve this further you could skip numbers which will not result in an eligible sum by starting the range at the floor of possible numbers.
x + x + 4 + x + 6 + x + 10 + x + 12 + x + 16 = 6x + 48
which is supposed to be above your sum_limit
6x + 48 >= sum_limit
x >=(sum_limit - 48) / 6
So if your range starts at x you will skip all numbers which would not result in an eligible sum anyway.
You would also be able to improve runtime by skipping even numbers in your loop(via range(y,x,2)).
Further improving the runtime would require you to adjust the isPrime function.
I wish to optimize and speed up this py in Python 2.7, which finds Mersenne Primes and filters non-mersenne primes and filters even numbers. The number 2 does not work, but that's ok. The code finds M44497 in 26 seconds. On a faster CPU it finds it in 15 seconds. It found M859433 in 7.5 hours. How can I say make M44497 run in under 7 seconds just hoping you guys know.
import time
def myfunction():
myfunction()
def prime_sieve():
yield 2; yield 3; yield 5; yield 7;
def mod_mersenne(n, prime, mersenne_prime):
while n > mersenne_prime:
n = (n & mersenne_prime) + (n >> prime)
if n== mersenne_prime:
return 0
return n
def is_mersenne_prime(prime, mersenne_prime):
s = 4
for i in range(prime - 2):
s = mod_mersenne((s*s - 2), prime, mersenne_prime)
return s == 0
def calculate_perfects(n):
primes = prime_sieve()
next(primes)
if is_mersenne_prime(n,(2**n - 1) ):
yield((2**n-1 ))
print ("Mersenne Determinate Program Tom O'Neil, The Program only prints Mersenne
Primes and it filters non-mersenne primes and even numbers. The number 2 returns
nothing!")
def runpro():
keep_running = True
num = int(input('Enter a number to test: '))
while keep_running:
start = time.time()
for perfect in calculate_perfects(num):
print ((True))
elapsed = time.time() - start
print "\tfound in %.f seconds" % elapsed
start = time.time()
num = int(input('Enter a number to test: '))
if num == 0:
keep_running = False
runpro()
You can employ gmpy2, i created a program that does both and you can see that gmpy2 can solve it in just over 2 seconds:
def makersmarknongmpy2(n):
z = 9
mask = (1<<n)-1
def mer_rem(x, bits):
# Below is same as: return x % mask
while True:
r = 0
while x != 0:
r += x & mask
x >>= bits
if r == mask:
r = 0
if r < mask:
return r
x = r
for x in range(n-1):
z = mer_rem(z * z, n)
return z == 9
import gmpy2
def makersmark(n):
z = 9
mask = gmpy2.mpz((1<<n)-1)
def mer_rem(x, bits):
# Below is same as: return x % mask
while True:
r = gmpy2.mpz(0)
while x != 0:
r += x & mask
x >>= bits
if r == mask:
r = gmpy2.mpz(0)
if r < mask:
return r
x = r
z = gmpy2.mpz(z)
n = gmpy2.mpz(n)
for x in range(n-1):
z = mer_rem(z * z, n)
return z == 9
start = time.time()
print(makersmark(44497)
end = time.time()
print(end-start)
True
2.0241031646728516
start = time.time()
print(makersmarknongmpy2(44497)
end = time.time()
print(end-start)
True
16.902064561843872
I am to measure how much time does it take for the function below to represent: C in range [0, 10] with the numbers in list N. (M measurements for each C).
import itertools
def amount(C):
N = [1, 2, 5]
#N = list(N)
N = sorted(N)
while C < max(N):
N.remove(max(N))
res = []
for i in range(1, C):
for j in list(itertools.combinations_with_replacement(N, i)):
res.append(sum(list(j)))
m = 0
for z in range (0, len(res)):
if res[z] == C:
m += 1
if N[0] == 1:
return m + 1
else:
return m
EDITED:
import itertools
def amount(C):
N = [1, 2, 5]
res = []
for i in range(1, C):
for j in list(itertools.combinations_with_replacement(N, i)):
res.append(sum(list(j)))
m = 0
for z in range (0, len(res)):
if res[z] == C:
m += 1
if N[0] == 1:
return m + 1
else:
return m
I would like to make 10 measurements and then take for example median of all those measurements.
There is my code but something unfortunately doesn't work properly and I have no idea what is wrong:
import time
def time_counter(amount, n=11, M=11):
res = list(range(n))
def count_once():
start = time.perf_counter()
amount(res)
return time.perf_counter() - start
return [count_once() for m in range(M)]
You are again passing a list and trying to do range(1,C) where C is a list
Here is how your program should be
import itertools
import time
def amount(C):
N = [1, 2, 5]
res = []
for i in range(1, C):
for j in list(itertools.combinations_with_replacement(N, i)):
res.append(sum(list(j)))
m = 0
for z in range (0, len(res)):
if res[z] == C:
m += 1
if N[0] == 1:
return m + 1
else:
return m
def time_counter(amount, n=11, M=11):
res = list(range(n))
def count_once(c):
start = time.perf_counter()
amount(c)
return time.perf_counter() - start
return [count_once(m) for m in range(M)]
#testing
print(time_counter(amount))