Лучший ответ зависит от того, что вы подразумеваете под «умным». Эффективный с точки зрения памяти подход состоит в том, чтобы шагать по массиву 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]]