</>
Topic 11 of 18

Course materials are currently available in Russian only.

Двумерные массивы

Дневник UNIX'оида · The video is optional — everything you need is in the text below.Open on YouTube ↗

Многие данные естественно записываются таблицей: игровое поле, карта, расписание, изображение из пикселей. В Python таблицу хранят как список списков.

Список списков

table = [
    [1, 2, 3],
    [4, 5, 6],
]
print(table[0])       # [1, 2, 3] — первая строка
print(table[1][2])    # 6 — строка 1, столбец 2
print(len(table))     # 2 — число строк
print(len(table[0]))  # 3 — число столбцов

Запись table[i][j]: сначала выбираем строку i, потом в ней элемент j. Нумерация, как всегда, с нуля.

Создание таблицы

Таблица n × m из нулей создаётся генератором:

n, m = 3, 4
grid = [[0] * m for _ in range(n)]

Не делай так: [[0] * m] * n. Это n ссылок на одну и ту же строку — изменишь одну клетку, изменится целый столбец.

Чтение таблицы

Если в каждой строке входа — числа через пробел:

n, m = map(int, input().split())
a = []
for _ in range(n):
    row = list(map(int, input().split()))
    a.append(row)

То же короче: a = [list(map(int, input().split())) for _ in range(n)].

Если строка входа — символы без пробелов (карта, поле игры), её удобно хранить как строку: grid = [input() for _ in range(n)], и тогда grid[i][j] — символ. Строку нельзя менять по индексу; если клетки нужно менять, преврати её в список: list(input()).

Обход таблицы

for i in range(n):
    for j in range(m):
        print(a[i][j], end=" ")
    print()

Можно перебирать и сами строки: for row in a: — тогда row это список чисел строки. Сумма всех чисел таблицы: sum(sum(row) for row in a).

Печать строки чисел через пробел — print(*row).

Строки и столбцы

row_sums = [sum(row) for row in a]                 # сумма каждой строки
col_sums = [sum(a[i][j] for i in range(n)) for j in range(m)]   # каждого столбца

Главная диагональ квадратной таблицы — клетки a[i][i], побочная — a[i][n - 1 - i].

Соседи клетки

Во многих задачах на сетках нужно посмотреть на соседей клетки (i, j). Удобно перечислить сдвиги:

# четыре соседа по сторонам
for di, dj in ((-1, 0), (1, 0), (0, -1), (0, 1)):
    ni, nj = i + di, j + dj
    if 0 <= ni < n and 0 <= nj < m:
        print("сосед", ni, nj)

Проверка 0 <= ni < n and 0 <= nj < m обязательна. Без неё на краю поля получится индекс -1, а в Python a[-1] — не ошибка, а последний элемент. Программа молча посчитает соседа с противоположного края, и ответ будет неверным.

Направления движения

Когда по таблице «ходят» (робот, змейка, обход), направления хранят в списках:

di = [-1, 0, 1, 0]    # вверх, вправо, вниз, влево
dj = [0, 1, 0, -1]
d = 1                 # смотрим вправо
d = (d + 1) % 4       # поворот по часовой стрелке → вниз

Остаток % 4 замыкает направления в кольцо: после «влево» снова «вверх».

Итог

  • таблица — список списков, a[i][j] — строка i, столбец j;
  • создавай через [[0] * m for _ in range(n)], не через * n;
  • читай построчно: числа через map, символьные сетки — как строки;
  • проверяй границы при обращении к соседям: a[-1] не вызывает ошибку;
  • направления удобно хранить списками сдвигов.