Цикл for
При написании программ зачастую встаёт задача сделать однотипное действие много раз. Например, перебрать все числа от \(1\) до \(10\) и для каждого выполнить одинаковый код. Для многократного повторения одного участка кода предусмотрены циклы.
Более сложный, но при этом самый распространённый цикл — цикл for
.
Выглядит он так:
for ‹переменная-счётчик› in range(‹начало›, ‹конец›, ‹шаг›):
# тело цикла
Давайте разберёмся, что означает каждая часть, на примере. Цикл ниже выполняет print(f"{i}")
для \(i\) от \(0\) до (но не включая) \(3\):
for i in range(0, 3, 1):
print(f"{i}")
0
1
2
Одно выполнение тела цикла по-научному называется итерация. Цикл в примере выше совершает три итерации.
Рассмотрим конструкцию for
подробней. Код выше будет представлять собой такую инструкцию:
- Начать отсчет с \(0\) и остановиться, не доходя до числа \(3\).
- Каждое отсчитанное значение сохранять в переменной \(i\).
- Выводить на экран значение переменной \(i\).
Если записать этот код без цикла for
, он будет выглядеть примерно так:
i = 0
print(f"{i}")
i += 1
print(f"{i}")
i += 1
print(f"{i}")
Выходит, цикл избавил от необходимости писать четырех дополнительных строк кода. Хорошие программисты терпеть не могут делать одно и то же несколько раз, поэтому цикл — одна из самых популярных программных конструкций.
Примеры функции range()
# 5 чисел, начиная с 0
for i in range(5):
print(f"{i}", end=" ")
# 0 1 2 3 4
# числа от 3 до 6 (не включительно)
for i in range(3, 6):
print(f"{i}", end=" ")
# 3 4 5
# числа от 1 до 10 (не включительно) с шагом 2
for i in range(1, 10, 2):
print(f"{i}", end=" ")
# 1 3 5 7 9
# числа от 0 до -10 (не включительно) с шагом -1
for i in range(0, -10, -1):
print(f"{i}", end=" ")
# 0 -1 -2 -3 -4 -5 -6 -7 -8 -9
Пример 1
Выведите \(5\) раз название кружка «Спортивное программирование».
for i in range(5):
print(f"Спортивное программирование")
Спортивное программирование
Спортивное программирование
Спортивное программирование
Спортивное программирование
Спортивное программирование
Пример 2
Составьте число из \(n\) цифр, возрастающих от \(1\) до \(n\).
n = int(input())
for i in range(1, n + 1):
print(f"{i}", end='')
3
123
Пример 3
Выведите по возрастанию первые \(n\) квадратов.
n = int(input())
for i in range(1, n + 1):
x = i ** 2
print(f"{x}", end=' ')
5
1 4 9 16 25
Пример 4
Выведите все целые четные числа, принадлежащие отрезку \([a;b]\) в возрастающем порядке.
a, b = map(int, input().split())
if a % 2 == 1:
a += 1
for i in range(a, b + 1, 2):
print(f"{i}", end=' ')
3 10
4 6 8 10
Оператор break
Оператор break
служит для досрочного выхода из цикла. Например, для цикла for
:
age = 10
for i in range(1, 100):
print(f"отсчёт {i}")
if i == age:
print(f"закончили считать")
break
отсчёт 1
отсчёт 2
отсчёт 3
отсчёт 4
отсчёт 5
отсчёт 6
отсчёт 7
отсчёт 8
отсчёт 9
отсчёт 10
закончили считать
Слово else
, примененное в цикле for
, проверяет, был ли произведен выход из цикла оператором break
, или же "естественным" образом. Блок инструкций внутри else
выполнится только в том случае, если выход из цикла произошел без помощи break
.
for i in range(10, 100):
if -9 <= i <= 9:
print(f"{i} - однозначное число")
break
else:
print(f"однозначных чисел в цикле нет")
Оператор continue
Оператор continue
позволяет «перескочить» к следующему повтору цикла, так что следующая после continue
часть тела цикла будет пропущена. В отличие от break
происходит не выход из цикла, а досрочное завершение текущего повтора с переходом к следующему.
Оператор используют, если понятно, что на текущем повторе цикла делать больше нечего.
for i in range(1, 16):
if i % 2 == 0:
print(f"{i} - чётное число")
continue
print(f"{i} - нечётное число")
1 - нечётное число
2 - чётное число
3 - нечётное число
4 - чётное число
5 - нечётное число
6 - чётное число
7 - нечётное число
8 - чётное число
9 - нечётное число
10 - чётное число
11 - нечётное число
12 - чётное число
13 - нечётное число
14 - чётное число
15 - нечётное число
Для чётных значений \(i\), оператор continue
прекращает выполнение тела цикла и передаёт управление на следующую итерацию for
(со следующим числом). Таким образом, нечётные значения \(i\) выводятся без условия.
Оператор continue
можно использовать вместо вложенного условного кода или для оптимизации цикла.
Циклический ввод
При написании циклов нередко нужно, чтобы наша программа обрабатывала входные данные в цикле определённое количество раз либо пока не произошло какое-то событие.
Пример 1
Выведите \(n\) вещественных чисел, которые заданы во входных данных.
n = int(input())
for i in range(n):
a = float(input())
print(f"{a}")
4
0.12
3.4
5.67
8.9
0.12
3.4
5.67
8.9
Пример 2
Увеличьте на \(1\) все \(n\) чисел, которые заданы во входных данных.
n = int(input())
for i in range(n):
a = int(input())
a += 1
print(f"{a}")
2
9
-5
10
-4
Пример 3
Найдите последнюю цифру всех \(n\) чисел, которые заданы во входных данных.
n = int(input())
for i in range(n):
a = int(input())
x = a % 10
print(f"{x}")
3
2024
6
23
4
6
3
Пример 4
Среди всех \(n\) чисел, которые заданы во входных данных, найдите однозначные.
n = int(input())
for i in range(n):
a = int(input())
if -9 <= a <= 9:
print(f"{a}")
3
-7
15
4
-7
4
Вложенные циклы
Часто в программировании решаются задачи, в которых требуется использовать цикл внутри другого цикла. Такие циклы называют вложенными.
Хорошим примером работы вложенного цикла служат часы. Секундная, минутная и часовая стрелки вращаются вокруг циферблата. Часовая стрелка смещается всего на \(1\) шаг для каждых \(60\) шагов минутной стрелки. И секундная стрелка должна сделать \(60\) шагов для \(1\) шага минутной стрелки. Это означает, что для каждого полного оборота часовой стрелки (\(12\) шагов), минутная стрелка делает \(720\) шагов.
Рассмотрим цикл, который частично моделирует электронные часы. Он показывает секунды от \(0\) до \(59\):
for s in range(60):
print(f"{s}")
Можно добавить переменную \(m\) и вложить цикл написанный выше внутрь еще одного цикла, который повторяется \(60\) раз:
for m in range(60):
for s in range(60):
print(f"{m} : {s}")
Для того, чтобы сделать модель законченной, можно добавить еще одну переменную для подсчета часов:
for h in range(24):
for m in range(60):
for s in range(60):
print(f"{h} : {m} : {s}")
Результатом работы такого кода будет:
0 : 0 : 0
0 : 0 : 1
0 : 0 : 2
...
23 : 59 : 58
23 : 59 : 59
Самый внутренний цикл сделает \(60\) итераций для каждой итерации среднего цикла. Средний цикл сделает \(60\) итераций для каждой итерации самого внешнего цикла. Когда самый внешний цикл сделает \(24\) итерации, средний сделает \(24 \cdot 60 = 1440\) итераций, и самый внутренний цикл сделает \(24 \cdot 60 \cdot 60 = 86400\) итераций!
Пример имитационной модели часов подводит нас к нескольким моментам, имеющим отношение к вложенным циклам:
- Вложенный цикл выполняет все свои итерации для каждой отдельной итерации внешнего цикла.
- Вложенные циклы завершают свои итерации быстрее, чем внешние циклы.
- Для того, чтобы получить общее количество итераций вложенного цикла, надо перемножить количество итераций всех циклов.
Давайте рассмотрим следующую задачу: требуется сгенерировать все возможные комбинации строчных букв английского алфавита длиной два символа. Вот как можно решить эту задачу:
for i in range(97, 123):
ch1 = chr(i)
for j in range(97, 123):
ch2 = chr(j)
text = ch1 + ch2
print(f"{text}")
Задача решена полным перебором букв алфавита. В начале программы запускается внешний цикл, который отвечает за генерацию первой буквы. Внешний цикл фиксирует очередное значение итерируемой переменной \(i\) — это будет код первой буквы.
Далее запускается внутренний цикл, отвечающий за генерацию второй буквы и изменяющий значение итерируемой переменной \(j\). Она также содержит код второй буквы. Таким образом, за одну итерацию внешнего цикла внутренний цикл совершает все свои итерации. Процесс повторяется, пока все свои итерации не совершит внешний цикл.
Операторы break
и continue
во вложенных циклах
Оператор break
выполняет прерывание ближайшего цикла в котором он расположен. Аналогично, оператор continue
осуществляет переход на следующую итерацию ближайшего цикла.
Рассмотрим программный код:
for i in range(3):
for j in range(3):
print(f"{i} {j}")
Результатом его выполнения будут \(9\) строк:
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
Изменим код, добавив во вложенный цикл условный оператор if
и оператор break
:
for i in range(3):
for j in range(3):
if i == j:
break
print(f"{i} {j}")
Результатом выполнения нового кода будут \(3\) строки:
1 0
2 0
2 1
Изменим оператор прерывания break
на оператор continue
:
for i in range(3):
for j in range(3):
if i == j:
continue
print(f"{i} {j}")
Результатом выполнения нового кода будут \(6\) строк:
0 1
0 2
1 0
1 2
2 0
2 1
Так как операторов break
в цикле может быть много, то анализировать такие программы становится тяжело из-за того, что сложно сказать, где будет точка выхода из цикла для разных входных данных. Поэтому использованием данного оператора лучше не злоупотреблять.
Дополним пример с генерацией двухбуквенных строк условием: сгенерировать последовательно двухбуквенные строки по алфавиту до строки «ya».
flag = False
for i in range(97, 123):
ch1 = chr(i)
for j in range(97, 123):
ch2 = chr(j)
text = ch1 + ch2
print(f"{text}")
if text == 'ya':
flag = True
break
if flag:
break
В программе по-прежнему используются вложенные циклы. Генерация и вывод происходят без изменений. Обратите внимание на переменную-флаг flag
логического (булева) типа. Она нужна для сигнала, что программа дошла до заданной комбинации букв и требуется остановить внешний цикл, так как break
во внутреннем цикле остановит только внутренний цикл.
Обычно флаг устанавливают в начальное значение False
(флаг опущен), а при выполнении какого-то условия в программе флаг устанавливают в значение True
(флаг поднят). При генерации комбинации «ya» происходит вывод этой комбинации, «поднятие» флага и остановка внутреннего цикла. После завершения внутреннего цикла происходит проверка состояния флага, и если флаг поднят, то останавливается и внешний цикл.
Пример 1
Выведите таблицу размером \(n \times m\), состоящую из символа #
.
n = int(input())
m = int(input())
for i in range(n):
for j in range(m):
print(f"#", end="")
print()
3
5
#####
#####
#####
Пример 2
Запустите \(n\) самолётиков через каждые \(5\) секунд.
n = int(input())
for i in range(1, n + 1):
for j in range(1, 6):
print(f"{j} сек.")
print(f"Пуск {i}го самолётика!")
2
1 сек.
2 сек.
3 сек.
4 сек.
5 сек.
Пуск 1го самолётика!
1 сек.
2 сек.
3 сек.
4 сек.
5 сек.
Пуск 2го самолётика!
Пример 3
Выведите таблицу размером \(n \times n\) (\(n\) – чётное), состоящую только из чисел \(1\) и \(2\). В первой половине строк выведите \(1\), а в оставшейся половине – \(2\).
n = int(input())
k = n // 2
for i in range(n):
for j in range(n):
if i < k:
print(f"1", end=' ')
else:
print(f"2", end=' ')
print()
6
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
2 2 2 2 2 2
2 2 2 2 2 2
2 2 2 2 2 2
Пример 4
Постройте числовой прямоугольник размером \(n \times m\), состоящий из различных чисел от \(1\) до \(n \cdot m\) в обратном порядке.
n, m = map(int, input().split())
k = n * m
for i in range(n):
for j in range(m):
print(f"{k}", end=' ')
k -= 1
print()
4 3
12 11 10
9 8 7
6 5 4
3 2 1
Пример 5
Постройте числовой прямоугольник, состоящий из \(5\) столбцов и \(n\) чисел в нём.
n = int(input())
k = 1
flag = False
for i in range(n):
for j in range(5):
print(f"{k}", end=" ")
if k == n:
flag = True
break
k += 1
if flag:
break
print()
17
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17
Пример 6
Найдите все пары чисел \(x\) и \(y\), которые в сумме равные \(s\). \((0 \le x \le y \le s)\)
s = int(input())
for x in range(s + 1):
for y in range(x, s + 1):
if x + y == s:
print(f"{x} {y}")
10
0 10
1 9
2 8
3 7
4 6
5 5