Iterating over a dynamic number for loops (Python)

I use python to sequence some numbers. I would like to create a function that allows me to enter a value (4, 8, 16, 32, 64, etc.), create an array of numbers and change their sequence.

I added numbers that describe in detail how to determine the sequence for values ​​= 4 and 8.

For value = 4, the array (x = [0, 1, 2, 3]) must be split into two ([0,1] and [2,3]) and then merged based on the first number in each array ([0 , 2, 1, 3]).

Figure with sequence for value = 4

For value = 8, the array (x = [0, 1, 2, 3, 4, 5, 6, 7]) should be divided into two ([0, 1, 2, 3] and [4, 5, 6, 7] ) Both arrays should be divided into two ([0, 1, 2, 3] in [0,1] and [2,3] and [4, 5, 6, 7] in [4,5] and [6, 7] ) Then the arrays should be combined based on the first number in each array and the sequence of the second set of arrays ([0, 4, 2, 6, 1, 5, 3, 7]).

Figure for sequence for value = 8

I don't know how to handle recursion (dynamically nested for loops). I try to go through each brek that is created by a split array. I looked at itertools and recursion ( Function with a different number of For Loops (python) loops ), but I could not get it to work. I have added code below to illustrate my approach so far.

Any help is greatly appreciated. I am also open to other ideas for sequencing.

I am using python 2.7.6 and numpy.

the code:

import numpy value = 4 a = [] x = numpy.arange(value) y = numpy.array_split(x, 2) for i in range(2): for j in y: a.append(j.tolist()[i]) print(a) 

Output:

 [0, 2, 1, 3] 

the code:

 import numpy value = 8 a = [] x = numpy.arange(value) y = numpy.array_split(x, 2) for i in range(2): for h in range(2): for j in y: z = numpy.array_split(j, 2) a.append(z[h][i]) print(a) 

Output:

 [0, 4, 2, 6, 1, 5, 3, 7] 

The output for value = 16 should be [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7 15].

+7
python arrays numpy for-loop
source share
3 answers

Here NumPythonic uses np.transpose and reshaping -

 def seq_pow2(N): shp = 2*np.ones(np.log2(N),dtype=int) return np.arange(N).reshape(shp).transpose(np.arange(len(shp))[::-1]).ravel() 

Please note that .transpose(np.arange(len(shp))[::-1] will simplify .T , so we will have a simplified version -

 def seq_pow2(N): shp = 2*np.ones(np.log2(N),dtype=int) return np.arange(N).reshape(shp).T.ravel() 

You can simplify and completely replace transposition by doing ravel / flattening in column order, as in fortran , with .ravel('F') to finally bring us to -

 def seq_pow2(N): shp = 2*np.ones(np.log2(N),dtype=int) return np.arange(N).reshape(shp).ravel('F') 

Run Examples -

 In [43]: seq_pow2(4) Out[43]: array([0, 2, 1, 3]) In [44]: seq_pow2(8) Out[44]: array([0, 4, 2, 6, 1, 5, 3, 7]) In [45]: seq_pow2(16) Out[45]: array([ 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]) 
+2
source share

A recursive version of python for clarity:

 def rec(n): if n==1 : return [0] l=[0]*n l[::2]=rec(n//2) for i in range (0,n,2) : l[i+1]=l[i]+n//2 return l 

for

 In [6]: rec(16) Out[6]: [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15] 

Or, observing the binary representation of the result, the numpy solution:

 def rearange(N): u=2**arange(N.bit_length()-1) v=arange(N) bits= u[None,:] & v[:,None] return sum(bits*u[::-1],1) 
+2
source share

The easiest way to do this is not to use for loops, but to do some array manipulation with numpy.

 N = 8 pow2 = np.log2(N) out = np.arange(N).reshape([2]*pow2).transpose(np.arange(pow2)[::-1]).flatten() array([0, 4, 2, 6, 1, 5, 3, 7]) 

What this means is that it converts x to an n dimensional array, where n is a power of 2 corresponding to the length of x . After this adjustment, the length of each dimension is 2. Then we change all sizes and smooth to get the desired array.

Edit

This is a similar approach to Divakar Solution , and in the end he did it much more succinctly, but I'll just leave it here for posterity.

+1
source share

All Articles