x = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]

Вращение на 1 единицу должно дать:

x = [[4, 1, 2],
     [7, 5, 3],
     [8, 9, 6]]

По сути, я хочу сдвинуть каждый круговой слой в массиве на «n» единиц.

Я посмотрел на numpy.roll, но не смог понять, использовать ли его в этом случае. Я не могу использовать процедуры поворота изображения, такие как scipy.ndimage.interpolation.rotate, так как они меняют форму и не совсем достигают желаемого результата.

< Сильный > Edit:

Для матрицы 4 X 4:

x = [[a, b, c, d],
     [e, f, g, h],
     [i, j, k, l],
     [m, n, o, p]]

Вращение на 1 единицу должно дать:

x = [[e, a, b, c],
     [i, j, f, d],
     [m, k, g, h],
     [n, o, p, l]]

< Сильный > Edit:

Добавим некоторые пояснения о том, как это работает для произвольных размеров.

Для матрицы N X N, повернутой на 1 единицу, внешнее «кольцо» сначала сдвигается на 1. Та же логика повторяется с оставшейся «внутренней» (N-2) X (N-2) матрицей.

4
ragha 6 Янв 2017 в 12:23

3 ответа

Лучший ответ

Вот подход, предполагающий, что вы хотите повернуть так, чтобы величина смещения была постоянной для срезов, где под срезом мы подразумеваем самый внешний слой элементов, направленных наружу от центра -

def outer_slice(x):
    return np.r_[x[0],x[1:-1,-1],x[-1,:0:-1],x[-1:0:-1,0]]

def rotate_steps(x, shift):
    out = np.empty_like(x)
    N = x.shape[0]
    idx = np.arange(x.size).reshape(x.shape)
    for n in range((N+1)//2):
        sliced_idx = outer_slice(idx[n:N-n,n:N-n])
        out.ravel()[sliced_idx] = np.roll(np.take(x,sliced_idx), shift)
    return out

Пробные прогоны

Дело № 1 (массив 3 x 3):

In [444]: x
Out[444]: 
array([[24, 85, 97],
       [51, 33, 11],
       [86, 38, 33]])

In [445]: rotate_steps(x,shift=1)
Out[445]: 
array([[51, 24, 85],
       [86, 33, 97],
       [38, 33, 11]])

Дело № 2 (массив 4х4):

In [447]: x
Out[447]: 
array([[11, 70, 28, 13],
       [44, 41, 17, 82],
       [47, 32, 89, 25],
       [32, 20, 67, 98]])

In [448]: rotate_steps(x,shift=1)
Out[448]: 
array([[44, 11, 70, 28],
       [47, 32, 41, 13],
       [32, 89, 17, 82],
       [20, 67, 98, 25]])

In [449]: rotate_steps(x,shift=2)
Out[449]: 
array([[47, 44, 11, 70],
       [32, 89, 32, 28],
       [20, 17, 41, 13],
       [67, 98, 25, 82]])
2
Divakar 6 Янв 2017 в 12:48

Вы применяете перестановку к матрице. Перестановки обычно представлены векторами (i -> p [i]) и применяются к векторам. Вы можете представить перестановку матрицы в матрице, если хотите, перестановка будет матрицей пар, так что элемент в (i, j) переместится в m [i, j].

Как только вы построите матрицу, для применения перестановки достаточно простого цикла.

1
zmbq 6 Янв 2017 в 20:23