Question: Assuming there is a 1-D array/list which defines a color gradient I would like to use it in order to create a 2-D color gradient as follows: Let's for simplicity replace color information with a single numerical value for an example of a 1-D array/list: [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ]  To keep the gradient progressing diagonally with progress of the largest next value diagonally over the entire array I would like to transform the 1-D sequence into a 2D-array with deliberately chosen shape (i.e. width/height, i.e. number of rows x number of columns where row * columns == length of the 1-D gradient array) as follows: [[ 1 2 4 ] [ 3 6 7 ] [ 5 9 10 ] [ 8 12 13 ] [ 11 14 15 ]]  or [[ 1 2 4 7 10 ] [ 3 6 9 12 13 ] [ 5 8 11 14 15 ]]  or starting from a sequence: [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]  to [[ 1 2 4 7 ] [ 3 6 9 11 ] [ 5 10 13 14 ] [ 8 12 15 16 ]]  Is there a ready-to-use out of the box Python module or C-library capable to perform such reshaping of an array or need this special case be coded by hand? And if coding the loops by hand is necessary, what would be the most efficient way of doing this as the sequence I would like to transform is 256³ large in size? I there maybe already ready for use code for such reshaping/transformation out there in the deep space of the Internet I have failed to find asking both the search engines and the LLMs?

Answer: General idea From what I can see, this can be done in three steps:  Split the sequence in fragments as if they were diagonals of an array of a given shape. Separate the elements of each fragment by the parity of their index. Assemble a new array from the modified diagonal fragments.  Step 1. Split the sequence into diagonal fragments I think it will be enough to find the stopping points, so then we can slice the sequence with them. For this, we can apply the cumulative sum to a sequence of diagonal lengths: import numpy as np from numba import njit @njit def flat_diagonal_stops(height, width): '''Return a sequence of breakpoints separating a sequence of length height*width into a sequence of matrix diagonals of the shape (height, width) ''' min_dim = min(height, width) lengths = np.empty(height + width, dtype='int') lengths[:min_dim] = [*range(min_dim)] # diagonal lengths in the lower triangle lengths[min_dim:1-min_dim] = min_dim # diagonal lengths in the main body lengths[:-min_dim:-1] = lengths[1:min_dim] # diagonal lengths in the upper triangle return lengths.cumsum()  Step 2. Separate elements by index parity A sequence transformation like this: (0, 1, 2, 3, 4, 5) >>> (0, 2, 4, 5, 3, 1)  is actually a separation of elements by the parity of their positional index. Elements with an even index are shifted to the left, while the others - to the right in reverse order: @njit def separate_by_index_parity(arr): '''Return a numpy.ndarray filled with elements of arr, first those in even-numbered positions, then those in odd-numbered positions in reverse order ''' out = np.empty_like(arr) middle = sum(divmod(len(out), 2)) out[:middle] = arr[::2] out[:middle-len(out)-1:-1] = arr[1::2] return out  Step 3. Assemble the fragments as diagonals of a new array To do this, we can create a flat representation of the required output and work within it by slicing diagonal positions: @njit def assemble_diagonals_separated_by_parity(arr, height, width): '''Return a matrix of shape (height, width) with elements of the given sequence arr arranged along diagonals, where the elements on each diagonal are separated by the parity of their index in them ''' out = np.empty(height*width, dtype=arr.dtype) stops = flat_diagonal_stops(height, width) out_step = width + 1 for offset, (start, stop) in enumerate(zip(stops[:-1], stops[1:]), 1-height): # out_from: the first element of an off-diagonal # out_to : next after the last element of an off-diagonal # out_step: a stride to get diagonal items out_from = -offset*width if offset < 0 else offset out_to = out_from + (stop-start)*out_step # stop - start is equal to the diagonal size out[out_from:out_to:out_step] = separate_by_index_parity(arr[start:stop]) return out.reshape(height, width)  The result is a stacking of the modified sequence on diagonals from bottom to top and from left to right. To get other types of stacking, we combine flipping and transposing. For example, we can stack elements in the left-to-right and top-to-bottom order along anti-diagonals as follows (note the reverse order of dimensions (width, height) in a function call): height, width = 6, 4 arr = np.arange(1, 1+height*width) out = np.fliplr(assemble_diagonals_separated_by_parity(arr, width, height).T) print(out)  [[ 1 2 4 7] [ 3 6 9 11] [ 5 10 13 15] [ 8 14 17 19] [12 18 21 22] [16 20 23 24]]  Code for experiments import numpy as np from numba import njit @njit def flat_diagonal_stops(height, width): min_dim = min(height, width) lengths = np.empty(height + width, dtype='int') lengths[:min_dim] = [*range(min_dim)] lengths[min_dim:1-min_dim] = min_dim lengths[:-min_dim:-1] = lengths[1:min_dim] return lengths.cumsum() @njit def separate_by_index_parity(arr): out = np.empty_like(arr) middle = sum(divmod(len(out), 2)) out[:middle] = arr[::2] out[:middle-len(out)-1:-1] = arr[1::2] return out @njit def assemble_diagonals_separated_by_parity(arr, height, width): if height == 1 or width == 1: return arr.reshape(height, width).copy() out = np.empty(height*width, dtype=arr.dtype) stops = flat_diagonal_stops(height, width) out_step = width + 1 for offset, (start, stop) in enumerate(zip(stops[:-1], stops[1:]), 1-height): out_from = -offset*width if offset < 0 else offset out_to = out_from + (stop-start)*out_step out[out_from:out_to:out_step] = separate_by_index_parity(arr[start:stop]) return out.reshape(height, width) height, width = 6, 4 arr = np.arange(1, 1+height*width) out = np.fliplr(assemble_diagonals_separated_by_parity(arr, width, height).T) print(out)   P.S. Stack the data directly along anti-diagonals Let's specialize the assembly function to work directly with anti-diagonals, so as not to get confused with flip-transpose tricks. In this case, we have a shorter slicing step, and the starting point will be along the top and right edges. Everything else remains unchanged: @njit def assemble_antidiagonals_separated_by_parity(arr, height, width): if height == 1 or width == 1: return arr.reshape(height, width).copy() out = np.empty(height*width, dtype=arr.dtype) stops = flat_diagonal_stops(height, width) out_step = width - 1 for offset, (start, stop) in enumerate(zip(stops[:-1], stops[1:])): out_from = offset if offset < width else (offset-width+2)*width-1 out_to = out_from + (stop-start)*out_step out[out_from:out_to:out_step] = separate_by_index_parity(arr[start:stop]) return out.reshape(height, width)  >>> height, width = 8, 5 >>> arr = np.arange(1, 1+height*width) >>> out = assemble_antidiagonals_separated_by_parity(arr, height, width) >>> print(out) [[ 1 2 4 7 11] [ 3 6 9 13 16] [ 5 10 15 18 21] [ 8 14 20 23 26] [12 19 25 28 31] [17 24 30 33 35] [22 29 34 37 38] [27 32 36 39 40]]