'How can I speed up my calculations with loops? Python

I wrote this code. But it works very slowly.

I'm figuring out how many times I have to run the case generator to find numbers less than or equal to inv, in this case six. I count the number of attempts until a digit <= 6 is generated. I find inv equal to 1 and repeat the loop. Until inv is 0. I will keep trying to generate six digits <= 6.

And I will repeat all this 10 ** 4 degrees again to find the arithmetic mean.

Help me speed up this code. Works extremely slowly. I would be immensely grateful. Without third party libraries Thank!

import random

inv = 6

def math(inv):
    n = 10**4
    counter = 0
    while n != 0:
        invers = inv
        count = 0
        while invers > 0:
            count += 1
            random_digit = random.randint(1, 45)
            if random_digit <= invers:
                invers -= 1
                counter += count
                count = 0

        if invers == 0:
            n -= 1
            invers = inv
    
    print(counter/10**4)

math(inv)


Solution 1:[1]

Here is a simple way to accelerate your code as is using numba:

m2 = numba.jit(nopython=True)(math)

Timings in ipython:

%timeit math(inv) 1.44 s ± 16.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit -n 7 m2(inv) 10.4 ms ± 177 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

This speeds up your code by over 100x.

Solution 2:[2]

You don't need all those loops. numpy.random.randint() can generate an array of a given size with random integers between low and high, so np.random.randint(1, 45, (1000, 10000)) will generate a matrix of 500 rows and 10k columns filled with random numbers. Then all you need to do is count how which is the first row in each column that contains a 6 (Numpy: find first index of value fast). Then

max_tries = 1000
def do_math(inv):
    rands = np.random.randint(1, 45, (max_tries, 10000))
    first_inv = np.argmax(rands < inv, axis=0)
    counter = first_inv.mean()
    return counter

This is not exactly what you want your function to do, but I found all your loops quite convoluted so this should point you in the right direction, feel free to adapt this code to what you need. This function will give you the number of tries required to get a random number less than inv, averaged over 10000 experiments.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Brian Larsen
Solution 2 Pranav Hosangadi