Reputation: 27
I'm trying to solve a problem where I generate a three random number array and loop through it until the sum of it is below or equal to 21. My question is if there is a better/more performant way to do it than the following, just to adjust myself to the best practices.
rng = np.random.default_rng()
a = 1
while a == 1:
rints = rng.integers(low=1, high=11, size=3)
suma = np.sum(rints)
if (suma <= 21):
print(rints, suma)
break
Thanks!
Upvotes: 1
Views: 216
Reputation: 231375
In numpy
we prefer to use whole arrays, and do "many" things at once, rather than iterate.
For example, instead of generating the random numbers just 3 at a time, why not generate a lot (guess 20):
In [88]: rng = np.random.default_rng()
In [89]: rints= rng.integers(low=1, high=11, size=(20,3))
In [90]: rints
Out[90]:
array([[ 8, 2, 1],
[ 5, 3, 9],
[ 5, 3, 6],
[10, 3, 6],
[ 4, 9, 1],
[ 9, 8, 2],
[ 3, 3, 10],
[ 1, 3, 5],
[ 5, 6, 1],
[ 6, 7, 9],
[10, 4, 2],
[ 1, 8, 1],
[ 6, 7, 8],
[ 3, 7, 9],
[ 8, 10, 10],
[ 7, 6, 8],
[ 5, 1, 4],
[ 4, 9, 10],
[ 1, 8, 8],
[ 7, 1, 9]])
Then we can sum by 3s, and identify how many are qualify:
In [91]: rints.sum(axis=1)
Out[91]:
array([11, 17, 14, 19, 14, 19, 16, 9, 12, 22, 16, 10, 21, 19, 28, 21, 10,
23, 17, 17])
In [92]: np.nonzero(_<=21)
Out[92]: (array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 18, 19]),)
Judging from this sample, your while
will be faster, since there's pretty high probability that an early set will qualify. Other other hand, if the criteria is >21, then we have to generate a lot more to get at least one.
Testing the efficiency of problems who's speed depends on random numbers is difficult, and maybe even meaningless. Depending on the numbers and the condition it could run quickly, or take a long time (e.g. test for sum >=30).
Upvotes: 0
Reputation: 91
Just a shorter form using itertools
import numpy as np
from itertools import dropwhile
rng = np.random.default_rng()
rints = list(dropwhile(lambda x: np.sum(x)>21, rng.integers(low=1, high=11, size=3)))
print(rints, np.sum(rints))
Upvotes: 1
Reputation: 4125
The while loop and the if statement can be combined. This will make it a little more efficient.
rng = np.random.default_rng()
target_value = 21
suma = 999
while suma >= target_value:
rints = rng.integers(low=1, high=11, size=3)
suma = np.sum(rints)
I would also suggest posting this to code review. They are more suited to these kind of questions.
Upvotes: 1