Следующая: , Предыдущая: functions, Вверх: Top


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

Создание массива

Самый простой способ создать в программе список из n элементов – использовать функцию range(n). Например, следующая программа

     A=range(5)
     print A

выведет на экран текст

     [0, 1, 2, 3, 4]

Теперь мы можем присваивать каждому элементу списка A новое значение. Например, мы можем сделать элемент A[0] также равным списку:

     A[0]=range[3]

Теперь A будет равно [[0, 1, 2], 1, 2, 3, 4], то есть объект A[0] будет списком [0, 1, 2]. В свою очередь, мы можем обращаться к отдельным элементам списка A[0]: A[0][0]==0, A[0][1]==1, A[0][2]==2.

На практике часто приходится иметь дело с прямоугольными таблицами данных, также называемых двумерными массивами. Их можно представлять в виде списка из n элементов (строк), каждый из которых является списком из m элементов (столбцов). Тогда к отдельному элементу двумерного массива A можн обращаться, как A[i][j], где i является номером строки, 0<=i<n, а j – номером столбца, 0<=j<m.

Итак, создадим массив A из n=3 строк и m=5 столбцов:

     n=3
     m=5
     A=range(n)           # A является списком из n строк
     for i in range(n):
         A[i]=range(m)    # Каждая строка является списком из m элементов
Заполнение массива

Теперь заполним массив нулями. Для этого нам понадобится два вложенных цикла: внешний цикл по всем строкам, а внутренний – по всем столбцам.

     for i in range(n):
         for j in range(m):
             A[i][j]=0

Если мы захотим записать в массив таблицу умножения, присвоив элементу A[i][j] значение i*j, последнюю строку в этом примере нужно записать в виде A[i][j]=i*j.

Вывод массива на экран

Конечно, можно вывести массив A на экран одной командой print A, но тогда все элементы будут выведены в одну строку:

     [[0, 0, 0, 0, 0], [0, 1, 2, 3, 4], [0, 2, 4, 6, 8]]

Но можно вывести массив в виде таблицы, так, чтобы каждая строка массива была выведена на одной строке, а внутри строки числа разделялись одним пробелом, то есть в виде:

     A[0][0] A[0][1] A[0][2] A[0][3] A[0][4]
     A[1][0] A[1][1] A[1][2] A[1][3] A[1][4]
     A[2][0] A[2][1] A[2][2] A[2][3] A[2][4]

Для этого снова понадобятся два вложенных цикла. Один цикл по всем строкам, другой – по всем столбцам. В результате получаем:

     for i in range(n):
         for j in range(m):
             print A[i][j],
         print

Обратите внимание на запятую, поставленную после инструкции print A[i][j], необходимую для того, чтобы печать продолжалась на этой же строке. А вот инструкцию print без параметров для перехода на новую строку мы даем после завершения внутреннего цикла, то есть после вывода всей строки на экран. Вот что получится:

     0 0 0 0 0
     0 1 2 3 4
     0 2 4 6 8
Считывание с клавиатуры

Теперь рассмотрим проблему считывания массива с клавиатуры в таком же виде. Проблема заключается в том, что функция input позволяет считать только одно значение, записанное в строке и выдаст ошибку при считывании набора чисел, разделенных пробелами. А функция raw_input сможет считать строку как единое целое вместе со всеми пробелами. Разбить строку на отдельные выражения, разделенные пробелами можно при помощи метода split(). Этот метод применяется к строке и возвращает список подстрок, состоящих из непробельных символов и разделенных пробелами. То есть если применить метод split к строке '1 2 3', то получится список из 3 строк: ['1', '2', '3']. Таким образом, мы можем разбить каждую входную строку на отдельные подстроки, а затем преобразовать эти подстроки к числовому виду при помощи функции int. В результате получаем следующий код (предполагается, что массив A из n строк и m столбцов уже создан):

     for i in range(n):        # Цикл по всем строкам
         s=raw_input()         # Считали строку в переменную s
         s=s.split()           # Разбили s на слова и записали их в виде списка
         for j in range(m):
             A[i][j]=int(s[j]) # Элементу A[i][j] присваиваем значение s[j]
Общий пример программы

Теперь объединим это все в одну программу, которая считывает с клавиатуры числа n и m (заданные в одной строке), затем создает массив из n строк и m столбцов, затем считывает его с клавиатуры построчно, затем увеличивает каждый элемент массива на 1, наконец, печатает результат:

     # Считываем размеры массива
     s=raw_input()
     s=s.split()
     n=int(s[0])
     m=int(s[1])
     
     # Создаем массив
     A=range(n)
     for i in range(n):
         A[i]=range(m)
     
     # Считываем массив с клавиатуры
     for i in range(n):
         s=raw_input()
         s=s.split()
         for j in range(m):
             A[i][j]=int(s[j])
     
     # Увеличиваем все элементы на 1
     for i in range(n):
         for j in range(m):
             A[i][j]=A[i][j]+1
     
     # Выводим массив на экран
     for i in range(n):
         for j in range(m):
             print A[i][j],
         print
Сложный пример обработки массива

Пусть дан квадратный массив из n строк и n столбцов. Необходимо элементам, находящимся на главной диагонали проходящей из левого верхнего угла в правый нижний (то есть тем элементам A[i][j], для которых i==j) присвоить значение 1, элементам, находящимся выше главной диагонали – значение 0, элементам, находящимся ниже главной диагонали – значение 2. То есть получить такой массив (пример для n==4):

     1 0 0 0
     2 1 0 0
     2 2 1 0
     2 2 2 1

Рассмотрим несколько способов решения этой задачи. Элементы, которые лежат выше главной диагонали – это элементы A[i][j], для которых i<j, а для элементов ниже главной диагонали i>j. Таким образом, мы можем сравнивать значения i и j и по ним определять значение A[i][j]. Получаем следующий алгоритм:

     for i in range(n):
         for j in range(n):
             if i<j:
                 A[i][j]=0
             elif i>j:
                 A[i][j]=2
             else:
                 A[i][j]=1

Данный алгоритм плох, поскольку выполняет одну или две инструкции if для обработки каждого элемента. Если мы усложним алгоритм, то мы сможем обойтись вообще без условных инструкций.

Сначала заполним главную диагональ, для чего нам понадобится один цикл:

     for i in range(n):
         A[i][i]=1

Затем заполним значением 0 все элементы выше главной диагонали, для чего нам понадобится в каждой из строк с номером i присвоить значение элементам A[i][j] для j=i+1, ..., n-1. Здесь нам понадобятся вложенные циклы:

     for i in range(n):
         for j in range(i+1,n):
             A[i][j]=0

Аналогично присваиваем значение 2 элементам A[i][j] для j=0, ..., i-1:

     for i in range(n):
         for j in range(0,i):
             A[i][j]=2

Можно также внешние циклы объединить в один и получить еще одно, более компактное решение:

     for i in range(n):
         for j in range(0,i):
             A[i][j]=2
         A[i][i]=1
         for j in range(i+1,n):
             A[i][j]=0
Форматирование чисел при выводе

Допустим, мы заполним массив таблицей умножения: A[i][j]=i*j как в примере в начале раздела. Если мы теперь попробуем вывести этот массив на экран, разделяя элементы в строке одним пробелом, то из-за того, что числа имеют различную длину столбцы таблицы окажутся неровными:

     0 0 0 0 0 0 0 0 0 0
     0 1 2 3 4 5 6 7 8 9
     0 2 4 6 8 10 12 14 16 18
     0 3 6 9 12 15 18 21 24 27

Для того, чтобы получить ровные столбцы необходимо, выводить числа так, чтобы одно выводимое число имело длину, например, ровно в 2 символа, а "лишние" позиции были бы заполнены пробелами.

       0  0  0  0  0  0  0  0  0  0
       0  1  2  3  4  5  6  7  8  9
       0  2  4  6  8 10 12 14 16 18
       0  3  6  9 12 15 18 21 24 27

Без лишних комментариев покажем, как в программе указать, что целое число x нужно выводить так, чтобы оно занимало ровно две позиции: print "%2d" % x. Здесь, естественно, можно заменить значение x на то значение, которое необходимо напечатать, а число 2 на любую другую ширину поля.

Итак, для печати ровной таблицы умножения можно воспользоваться следующим кодом:

     for i in range(n):
         for j in range(m):
             print "%2d" % A[i][j],
         print
Упражнения

Если в условиях задачи сказано "Дан двумерный массив", то программа получает на вход два числа n и m, являющиеся числом строк и столбцов в массиве. Далее во входном потоке идет n строк по m чисел, являющиеся элементами массива. Если в условиях задачи сказано "Дан квадратный массив", то в первой строке входных данных содержится только одно число n, далее идет n строк по n чисел в каждой.

  1. Дано число n. Создайте квадратный массив из n строк и n столбцов, и заполните его по следующему правилу:

    Числа на диагонали, идущей из правого верхнего в левый нижний угол равны 1.

    Числа, стоящие выше этой диагонали, равны 0.

    Числа, стоящие ниже этой диагонали, равны 2.

    Полученный массив выведите на экран. Числа разделяйте одним пробелом. Пример

              Вход                         Выход
              4                            0 0 0 1
                                           0 0 1 2
                                           0 1 2 2
                                           1 2 2 2
         
  2. Дано число n и квадратный массив из n строк и n столбцов. Проверьте, является ли массив симметричным относительно главной диагонали. Программа должна выводить слово yes для симметричного массива и слово no для несимметричного. Пример
              Вход                         Выход
              3                            yes
              0 1 2
              1 2 3
              2 3 4
         

    Указание. Для элемента A[i][j] симметричным ему является элемент A[j][i].

  3. Состязания-1. В метании молота состязается n спортcменов. Победителем считается тот спортсмен, у которого сумма результатов по всем броскам максимальна.

    Если перенумеровать спортсменов числами от 0 до n-1, а попытки каждого из них – от 0 до m-1, то на вход программа получает массив из n строк и m столбцов, заполненный неотрицательными числами. Программа должна определить максимальную сумму чисел в одной строке и вывести на экран эту сумму и номер строки, для которой достигается эта сумма. Если таких строк несколько, то выводится номер наименьшей из них. Пример для n=4 спортсменов и m=3 попыток:

              Вход                         Выход
              4 3                          19
              5 6 7                        1
              6 6 7
              7 6 6
              4 3 5
         

    Не забудьте, что нумерация строк (спортсменов) начинается с 0.

  4. Состязания - 2. Победителем соревнований объявляется тот спортсмен, у которого максимален наилучший результат. Таким образом, программа должна найти значение максимального элемента в данном массиве, а также его индексы (то есть номер спортсмена и номер попытки). Программа выводит значение максимального элемента, затем номер строки и номер столбца, в котором он встречается. Пример
              Вход                         Выход
              4 3                          5
              1 4 2                        1 0
              5 2 5
              5 1 4
              1 2 4
         

    Если в массиве несколько максимальных элементов, то нужно вывести минимальный номер строки, в которой встречается такой элемент, а если в этой строке таких элементов несколько, то нужно вывести минимальный номер столбца. Не забудьте, что все строки и столбцы нумеруются с 0.

  5. Состязания - 3. Будем считать, что побеждает спортсмен, у которого максимален наилучший бросок. Если таких несколько, то из них побеждает тот, у которого наилучшая сумма результатов по всем попыткам. Если и таких несколько, победителем считается спортсмен с минимальным номеров. Определите номер победителя соревнований.
              Вход                         Выход
              4 3                          2
              8 8 8
              5 9 3
              9 4 7
              6 6 2
         
  6. Состязания - 4. Будем считать, что победитель определяется по лучшему результату. Определите количество участников состязаний, которые разделили первое место, то есть определите количество строк в массиве, которые содержат значение, равное наибольшему.
              Вход                         Выход
              4 3                          2
              1 2 3
              4 5 6
              6 2 5
              2 3 4
         
  7. Состязания - 5. Решите предыдущую задачу, но на экран выведите еще и номера спортсменов, разделивших первое место. Сначала программа выводит количество спортсменов, показавших наилучший результат, затем – их номера в порядке возрастания.
              Вход                         Выход
              4 3                          2
              1 2 3                        1 2
              4 5 6
              6 2 5
              2 3 4
         
  8. Даны два числа n и m. Создайте двумерный массив из n строк и m столбцов, заполните его таблицей умножения A[i][j]=i*j и выведите на экран. При этом нельзя использовать вложенные циклы, все заполнение массива должно производиться одним циклом, например, for i in range(n*m):.
  9. Даны два числа n и m. Создайте двумерный массив C из n строк и m столбцов и заполните его по следующим правилам:

    Числа, стоящие в строке 0 или в столбце 0 равны 1 (A[0][j]=1, A[i][0]=1). Для всех остальных элементов массива A[i][j]=A[i-1][j]+A[i][j-1], то есть каждый элемент равен сумме двух элементов, стоящих слева и сверху от него. Выведите данный массив на экран, отводя на вывод каждого числа ровно 6 символов.

              Вход                         Выход
              4 6                          1    1    1    1    1    1
                                           1    2    3    4    5    6
                                           1    3    6   10   15   21
                                           1    4   10   20   35   56
         

    Что получилось в результате?

  10. Даны числа n и m. Создайте массив из n строк и m столбцов и заполните его следующей змейкой (ниже приведен пример для n=4 и m=6):
                 0   1   2   3   4   5
                11  10   9   8   7   6
                12  13  14  15  16  17
                23  22  21  20  19  18
         

    Выведите массив на экран, отводя на вывод каждого числа ровно 3 символа.

  11. Даны числа n и m. Создайте массив из n строк и m столбцов и заполните его следующим образом (ниже приведен пример для n=4 и m=6):
                 0   1   3   6  10  14
                 2   4   7  11  15  18
                 5   8  12  16  19  21
                 9  13  17  20  22  23
         

    Выведите массив на экран, отводя на вывод каждого числа ровно 3 символа.

  12. Дано число n. Создайте квадратный массив из 2*n+1 строк и 2*n+1 столбцов и заполните его по спирали начиная с числа 0 в центральной клетке A[n][n]. Спираль выходит вверх, далее закручивается против часовой стрелки. Выведите массив на экран, отводя на вывод каждого числа ровно 3 символа. Ниже приведен пример для n=2:
               12 11 10  9 24
               13  2  1  8 23
               14  3  0  7 22
               15  4  5  6 21
               16 17 18 19 20
         

Вход в тестирующую систему

Текущие результаты.