Python создает матрицу прокатки 1с по диагонали - PullRequest
0 голосов
/ 06 сентября 2018

Я хочу создать матрицу с n столбцами по k 1 в каждой строке, прокручивающейся слева направо. (n-k элементов в каждой строке 0) пример:

k = 4, n = 10

результат:

1 1 1 1 0 0 0 0 0 0  
0 1 1 1 1 0 0 0 0 0  
0 0 1 1 1 1 0 0 0 0  
0 0 0 1 1 1 1 0 0 0  
0 0 0 0 1 1 1 1 0 0  
0 0 0 0 0 1 1 1 1 0  
0 0 0 0 0 0 1 1 1 1 

как я могу создать эту матрицу быстро и умно?

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Лучший ответ зависит от того, что вы подразумеваете под «умным». Эффективный с точки зрения памяти подход состоит в том, чтобы шагать по массиву 1-й:

>>> import numpy as np
>>> from numpy.lib.stride_tricks import as_strided
>>> a = np.zeros(2*n-k, dtype=int)
>>> a[n-k:n] = 1
>>> view = as_strided(a[n-k:], shape=(n-k+1, n), strides=(-8, 8))
>>> view.tolist()
[[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]]

В этом представлении используется 16 целых чисел для массива из 70 целых чисел.

Альтернативный подход состоит в том, чтобы наблюдать, что у распределенного массива есть повторяющийся образец 4 единиц, сопровождаемых 7 нулями. Таким образом, вы можете добавить это и изменить форму:

>>> r = n-k+1
>>> np.tile([1]*k+[0]*r, r)[:-r].reshape(r,n)
array([[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
       [0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
       [0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
       [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]])

Если вы не хотите использовать NumPy и просто ищете прямой и Pythonic подход, вы можете бросить deque и накопить:

from collections import deque

data = [1]*k + [0]*(n-k)
d = deque(data)
result = [data]
while not d[-1]:
    d.rotate(1)
    result.append(list(d))

Возможна рассылка списков для компоновки - эта не моя, я обнаружил плохой фрагмент кода на холодном и грязном полу в чате # 6 . Автору не понравилось это настолько, чтобы опубликовать его (по общему признанию, он сидит где-то на размытой линии между «крутой однострочник» и «чем-то, что не должно быть однострочным»):

>>> [[1 if 0<=i-j<k else 0 for i in range(n)] for j in range(n-k+1)]
[[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]]
0 голосов
/ 06 сентября 2018

Вы можете использовать понимание списка:

[list(map(int, list(bin(2**10 + (2**4 - 1) * 2**expo)[3:]))) for expo in range(6, -1, -1)]

выход:

[[1, 1, 1, 1, 0, 0, 0, 0, 0, 0], 
 [0, 1, 1, 1, 1, 0, 0, 0, 0, 0], 
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0], 
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0], 
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0], 
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0], 
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...