1

I am trying to create a numpy array of the following type:

range = 3, size = 4    => [(0,0,0,0), (0,0,0,1) .... (0,0,0,3), (0,0,1,0)........(3,3,3,3)]

currently, I have got the solution of using itertool.combination to generate the list and then convert it into numpy array.

Is there any smarter and better / faster way to implement it? especially when the range and the size number both are going up to 50?

Axd
  • 45
  • 2
  • 1
    Following your example, range=1, size=2 would be a 1D array `[(0, 0), (0, 1), (1, 0), (1, 1)]`, correct? Do you actually want an array of tuples as you've shown (which is slow, generally speaking), or do you actually want a 2D array (4x2 in my example)? – John Zwinck Jun 26 '22 at 15:51
  • 2
    https://stackoverflow.com/questions/11144513/numpy-cartesian-product-of-x-and-y-array-points-into-single-array-of-2d-points – Nin17 Jun 26 '22 at 15:54
  • @Nin17 Shoot my bad, I wanted to cast a close vote for this, and the comment gets generated automatically. It's deleted now. – BrokenBenchmark Jun 26 '22 at 16:01
  • 2
    The best is not to create an array but compute the values on the flow (the memory is a very scarce resource). However, are you aware that you want to generate 23_906_104_021_463 billion billion billion billion billion billion billion billion combinations? All super-computer of the world together are not enough to generate all the combination during a whole life time... Not to mention that all computers on earth together does not have enough memory to store the resulting array. What about reconsidering your need to something physically **reasonable**? – Jérôme Richard Jun 26 '22 at 17:14

1 Answers1

0

Repeated broadcast assignment can achieve:

def combi(rng, size):
    rng += 1
    ar = np.empty((rng ** size, size), dtype=int)
    a = np.arange(rng)
    shape = (rng,) * size
    for col in ar.T[::-1].reshape(-1, *shape):
        col[...] = a
        a = a[..., None]
    return ar

Test:

>>> combi(2, 2)
array([[0, 0],
       [0, 1],
       [0, 2],
       [1, 0],
       [1, 1],
       [1, 2],
       [2, 0],
       [2, 1],
       [2, 2]])
>>> combi(1, 3)
array([[0, 0, 0],
       [0, 0, 1],
       [0, 1, 0],
       [0, 1, 1],
       [1, 0, 0],
       [1, 0, 1],
       [1, 1, 0],
       [1, 1, 1]])

But for your requirements, the shape of the generated array will reach (51 ** 50, 50). I think no machine can bear such an array.

Mechanic Pig
  • 6,756
  • 3
  • 10
  • 31