Это продолжение. Начало здесь: Подготовка
Для решения задачи напрашиваетcя элементарная логика: заполнить в цикле первую строку матрицы, а потом... а потом посмотрим. Давайте начнём:
for x in range(N): a[0][x] = x + 1
Обращение к a[0] даёт нам первую строку матрицы, а обращение к a[0][x] даёт нам элемент со смещением x в этой строке. Этому элементу мы присваиваем значение x + 1, так как элементы считаются с 0, а их значения – с 1.
Мы получим следующий результат:
[1, 2, 3, 4, 5]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
Теперь нужно заполнить вертикальный столбец справа. Напишем ещё один цикл:
for y in range(N): a[y][N-1] = N + y
Теперь цикл двигается не по х, а по y, и значит, мы перебираем не столбцы, а строки, обращаясь в них к столбцу со смещением N-1:
[1, 2, 3, 4, 5]
[0, 0, 0, 0, 6]
[0, 0, 0, 0, 7]
[0, 0, 0, 0, 8]
[0, 0, 0, 0, 9]
Теперь нужно заполнить нижнюю строку, двигаясь справа налево, а затем первый столбец, двигаясь снизу вверх. Так мы полностью замкнем первый виток спирали:
Но есть проблемы:
- Угловые клетки перезаписываются дважды, так как предыдущий цикл в них заканчивается, а новый начинается. Это не то что бы вредит, но зачем делать лишние действия?
- Нужно в каждом цикле продолжать натуральный ряд чисел, начиная с последнего значения.
- Последний (замыкающий) цикл должен быть короче на 1 клетку
Разобьём (мысленно, конечно) края матрицы на более подходящие отрезки и заодно посмотрим, какие для них нужно выбирать координаты и направления:
Циклы теперь имеют одну и ту же длину, которая всегда выражается в N-1. У каждого угла есть свои координаты, которые также задаются через N. Наконец, заведём переменную, в которой будем накапливать значение натурального ряда.
c = 1
for x in range(N-1): a[0][x] = c; c += 1
for y in range(N-1): a[y][N-1] = c; c += 1
for x in range(N-1): a[N-1][N-1-x] = c; c += 1
for y in range(N-1): a[N-1-y][0] = c; c += 1
Мы получили такой результат:
Осталось продолжать писать циклы, чтобы заполнить всю матрицу. Но сколько циклов писать, если N – произвольно заданное число? Давайте посмотрим, что получается, когда мы обошли матрицу по периметру 1 раз:
Если отбросить периметр, то в центре остаётся незаполненная матрица размером N-2 * N-2, которую мы можем точно так же заполнять по периметру. Затем опять отбросить периметр, перейти к внутренней матрице размером N-4 * N-4, и так до тех пор, пока оставшаяся матрица не станет размером 1*1.
Иначе говоря, четыре вышеуказанных цикла мы повторяем, постоянно задавая новый старт внутри матрицы и уменьшая начальный размер N на 2. Мы дойдём от угла матрицы до её центра по диагонали за N/2 шагов, значит, столько раз и нужно повторить наши циклы.
Вот полный код:
Если не помещается полностью, смотрите по ссылке.
Комментарии к коду:
- переменная start задаёт отступ от внешнего края оригинальной матрицы. Этот отступ увеличивается на 1 каждый раз, когда прогоняются 4 цикла по периметру.
- N // 2 это целочисленное деление на 2.
- N % 2 это остаток от деления на 2. Если N – нечётное число, то в центре останется пустая клетка, которую циклы заполнить не смогут. Её мы заполняем отдельно.
- Вывод на печать делаем ленивый: проходим циклом по строкам матрицы и выводим каждую строку с помощью print, не заморачиваясь форматированием.
Это первый способ решения.
Следующая часть: Вторая и моя реализации