§ 9.1. Программирование циклических алгоритмов. Цикл по коллекции (for)

Школьный курс C++
Содержание

Цикл по переменной

Цикл по переменной (или с параметром) for применяется в том случае, когда прежде выполнения инструкций тела цикла, становится известным количество шагов, которые должен выполнить этот цикл. Название цикла связано с тем, что в заголовке этого цикла всегда используется счетчик. Счетчику (i) присваивается начальное значение (a). В зависимости от языка, на каждом шаге цикла счетчик получает приращение (n, целое или дробное). Цикл заканчивает свою работу, когда значение счетчика приобретает максимально допустимое значение (b), определяемое в условии. Обычно блок-схема цикла изображается с помощью блока “модификация”:

Инструкция for

В python цикл по переменной реализует инструкция for. Синтаксис этой инструкции выглядит необычным образом:

for переменная_счетчик in последовательность:
    инструкции_1
[else:
    инструкции_2]

Дело в том, что цикл for в python предназначен для обхода последовательностей (англ. sequence) любого итерируемого типа.

Итерация – это однократный проход по телу цикла, его шаг. В широком смысле – это любой циклический процесс. Но в узком смысле, чаще всего, подразумевается организация циклических вычислений с помощью счетчика. Дело в том, что с помощью такого цикла можно перебирать адреса ячеек памяти в которых сохраняются элементы последовательностей (список, множество, кортеж, дек и др.). Итерация не является рекурсией. Подробно с понятиями рекурсия и последовательность мы познакомимся позднее.

Последовательность в for можно определять явно или использовать по имени. Приведем пример, в котором последовательность определяется явно.
Задача 1. Вывести на экран все степени числа 2 от 1 до 10.

Программа 9.1.1
p = 1
for i in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10):
    p *= 2
    print('2 ^{:>3} = {:>4}'.format(i, p))

Вывод

2 ^  1 =    2
2 ^  2 =    4
2 ^  3 =    8
2 ^  4 =   16
2 ^  5 =   32
2 ^  6 =   64
2 ^  7 =  128
2 ^  8 =  256
2 ^  9 =  512
2 ^ 10 = 1024

На каждом шаге цикла переменная i поочередно принимает все значения элементов последовательности. Когда будет передано значение последнего элемента последовательности, итерации прекратятся и цикл завершит свою работу.
Так же, как и цикл while, инструкция цикла for имеет необязательный блок else.

Функция range()

Чтобы расширить применение цикла for на задачи не относящиеся к обработке последовательностей и, тем самым, сделать его более универсальным, в python разработан класс range. Его назначение создавать произвольные целочисленные последовательности в виде прогрессий. Хотя в python и принято причислять range к типу последовательностей, но, на самом деле, последовательности, созданные range(), не являются таковыми. Дело в том, что range определяет только правила построения последовательности, сами же элементы в памяти не сохраняются.

Последовательность, созданная range(), может быть использована как основа для создания настоящих последовательностей.

Функция range() может применяться с одним, двумя или тремя аргументами:

  • range(a) – создается последовательность от 0 до a - 1[0, a-1] (a – не входит);
  • range(a, b) – создается последовательность от a до b[a, b) (b – не входит);
  • range(a, b, n) – создается последовательность от a до b[a, b) с шагом n (b – не входит, шаг может быть отрицательным).
Примеры совместного использования цикла for и функции range() приведены ниже:

Программа 9.1.2
for j in range(10):
    print(j, end=' ')
print()
for j in range(10, 100, 10):
    print(j, end=' ')
print()
for j in range(100, 50, -5):
    print(j, end=' ')

Вывод

0 1 2 3 4 5 6 7 8 9 
10 20 30 40 50 60 70 80 90 
100 95 90 85 80 75 70 65 60 55

Рассмотрим пример из учебника.
Задача 2. Дано целое n и действительное a. Вычислить an (целую степень действительного числа).

Программа 9.1.3
a = float(input('a = '))
n = int(input('n = '))
p = 1
for i in range(n):
    p = p * a
else:      
    print('{:}^{:} = {:.5f}'.format(a, n, p))

Вывод

a = 2.1
n = 5
2.1^5 = 40.84101

Блок-схема

В данной программе значение счетчика не используется. Переменная цикла i проходит по всем элементам последовательности от 0 до n-1. В результате, цикл сделает n итераций и мы получим искомое значение степени.

Количество шагов цикла не зависит от значения элементов последовательности range(). Если вы измените в текущей итерации значение счетчика, то вы измените только копию элемента последовательности, а не сам его элемент. Количество шагов цикла зависит только от количества элементов в последовательности и равно этому значению.

Часто значение счетчика используется в теле цикла для изменения какой-либо величины. Приведем пример с черепахой. В этой программе значение счетчика используется для изменения радиуса окружности на каждой итерации.
Задача 3. Построить в центре холста n разноцветных окружностей с общим центром так, чтобы окружность меньшего радиуса находилась поверх окружности с большим радиусом. Радиус r самой большой окружности ввести с клавиатуры.

Программа 9.1.4
import turtle as t
from random import random, seed
##################### Параметры холста ######################
seed()
w = t.Screen()
w.reset()
w.title('Окружности')
w.bgcolor('black')
w.setup(width = 600, height = 600, startx = -10, starty = 10)
#################### Параметры черепахи #####################
t.speed(10)
t.hideturtle()
###################### Решение задачи #######################
r = int(input('r = ')) # Радиус самой большой окружности
n = int(input('n = ')) # Количество окружностей
t.up()
t.goto(0, -r) # Устанавливаем по центру
t.down()
for i in range(n):
    R = random()
    G = random()
    B = random()
    t.fillcolor(R, G, B)
    t.begin_fill()
    t.circle(r - 30 * i) # Рисуем окружность
    t.end_fill()
    t.up() # Переходим к следующей
    t.lt(90)
    t.fd(30)
    t.rt(90)
    t.down()
w.exitonclick()
t.mainloop()

Возможный вывод
r = 250
n = 9

Вложенные циклы for

Для вложенных циклов, работающих от счетчика, чаще всего применяется цикл for, так как он представляет эту структуру в более компактной форме. Приведем простой пример.
Задача 4. Вывести таблицу умножения шестнадцатеричных чисел от 1 до 10 (1610).

Программа 9.1.5
for i in range(1, 17):
    for j in range(1, 17):
        print('{:>4X}'.format(i * j), end='')
    print()

Вывод

   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F  10
   2   4   6   8   A   C   E  10  12  14  16  18  1A  1C  1E  20
   3   6   9   C   F  12  15  18  1B  1E  21  24  27  2A  2D  30
   4   8   C  10  14  18  1C  20  24  28  2C  30  34  38  3C  40
   5   A   F  14  19  1E  23  28  2D  32  37  3C  41  46  4B  50
   6   C  12  18  1E  24  2A  30  36  3C  42  48  4E  54  5A  60
   7   E  15  1C  23  2A  31  38  3F  46  4D  54  5B  62  69  70
   8  10  18  20  28  30  38  40  48  50  58  60  68  70  78  80
   9  12  1B  24  2D  36  3F  48  51  5A  63  6C  75  7E  87  90
   A  14  1E  28  32  3C  46  50  5A  64  6E  78  82  8C  96  A0
   B  16  21  2C  37  42  4D  58  63  6E  79  84  8F  9A  A5  B0
   C  18  24  30  3C  48  54  60  6C  78  84  90  9C  A8  B4  C0
   D  1A  27  34  41  4E  5B  68  75  82  8F  9C  A9  B6  C3  D0
   E  1C  2A  38  46  54  62  70  7E  8C  9A  A8  B6  C4  D2  E0
   F  1E  2D  3C  4B  5A  69  78  87  96  A5  B4  C3  D2  E1  F0
  10  20  30  40  50  60  70  80  90  A0  B0  C0  D0  E0  F0 100

Блок-схема

Обратите внимание, что переменные внешнего и вложенного циклов должны иметь разные имена!
Вывод по образцу с помощью for тоже возможен.
Задача 5. Вывести числовой треугольник по образцу:

  1
  2  1
  3  2  1
  4  3  2  1
  5  4  3  2  1
  6  5  4  3  2  1
  7  6  5  4  3  2  1
  8  7  6  5  4  3  2  1
  9  8  7  6  5  4  3  2  1
Программа 9.1.6
for i in range(1, 11):
    for j in range(1, i):
        print('{:>3}'.format(i - j), end='')
    print()

Вывод см. выше
Здесь длина последовательности, создаваемой функцией range() для вложенного цикла, будет зависеть от значения i на текущей итерации.
Рассмотрим более сложный пример переборного алгоритма реализованного с помощью вложенных for.
Задача 6. Вывести таблицу истинности для логического выражения:
not(a v b) v (a ^ c),
где a, b и c – это логические переменные.

Программа 9.1.7
print('{:}{:>3}{:>3}{:>3}'.format('a', 'b', 'c', 'f'))
for a in (0, 1):
    for b in (0, 1):
        for c in (0, 1):
            print('{:}{:>3}{:>3}{:>3}'
                  .format(a, b, c, 
                          not(a or b) or a and c))

Вывод

a  b  c  f
0  0  0  1
0  0  1  1
0  1  0  0
0  1  1  0
1  0  0  0
1  0  1  1
1  1  0  0
1  1  1  1

Как видите, мы оказались правы – переборные циклы выполненные с помощью for выглядят значительно компактнее аналогичных c циклом while.
Заметим, что цикл одного типа может быть вложен в цикл другого типа.
Задача 7. Найти натуральное число от 100 до 1000 с максимальной суммой делителей

Программа 9.1.8
max = 0
for j in range(100, 1001):
    s = 0
    i = 2
    while i <= j // 2:
        if j % i == 0:
            s += i
        i += 1
    if s > max:
        max = s
        k = j
else:
    print(k)

Вывод

960

Рассмотрим пример с черепахой, которая мостит треугольную плитку на холсте с помощью вложенных циклов for.
Задача 8. Составить программу мощения черепахой равносторонней треугольной плиткой всей площади холста. Размер стороны плитки определить с клавиатуры.

Программа 9.1.9
import turtle as t
from math import sqrt
##################### Параметры холста ######################
w = t.Screen()
w.reset()
w.title('Плитка')
w.bgcolor('black')
w.setup(width = 600, height = 600, startx = -10, starty = 10)
#################### Параметры черепахи #####################
t.speed(10)
t.hideturtle()
t.goto(-300,300)
###################### Решение задачи #######################
d = int(input("Длина стороны -> "))
n = 600 // d # Определяем количество плиток
m = 600 // int(d * sqrt(3)) # количество рядов
for i in range(m + 1):    
    for j in range(n + 1):  # за один шаг рисуем 2 ряда        
        t.fillcolor("DeepSkyBlue4")        
        t.begin_fill()        
        for k in range(3):            
            t.fd(d)            
            t.rt(120)        
        t.end_fill()
        t.rt(60)
        t.fillcolor("dark turquoise")        
        t.begin_fill()        
        for k in range(3):            
            t.fd(d)
            t.rt(120)        
        t.end_fill()
        t.fd(d)
        t.fillcolor("dark turquoise")        
        t.begin_fill()        
        for k in range(3):            
            t.fd(d)            
            t.rt(120)        
        t.end_fill()
        t.rt(60)
        t.fillcolor("DeepSkyBlue4")        
        t.begin_fill()        
        for k in range(3):            
            t.fd(d)
            t.rt(120)        
        t.end_fill()
        t.lt(180)
        t.fd(d)
        t.rt(60)
    t.bk((n + 1) * d) # Перемещаемся к следующему ряду  
    t.rt(120)    
    t.fd(d)    
    t.lt(60)
    t.fd(d)
    t.lt(60)
w.exitonclick()
t.mainloop()

Вывод
d = 70

Замечаем, что в этой программе тоже наличествует повторяющийся код. На следующем уроке мы решим эту проблему.

Приложение

Примеры решения задач
Вопросы
Темы сообщений
Задания А
Задания Б
Задания С
Ссылки
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.


Обсуждение закрыто.