-2

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)
Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
Harry
  • 39
  • 6
  • 4
    Unrelated: `math` is a standard module in python. Not a good idea to give the same name to something else because it might cause confusion when someone else is reading your code. – Pranav Hosangadi Sep 23 '20 at 19:09
  • 1
    also if the code works okay and all you need is optimization/review, I think it is better to post it over [CodeReview StackExchange](https://codereview.stackexchange.com/) instead – Tibebes. M Sep 23 '20 at 19:13

2 Answers2

2

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.

Brian Larsen
  • 612
  • 8
  • 9
-1

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.

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70