Управляющий поток: условия и циклы
Всего два хода, которые есть у программы: выбрать путь булевой алгеброй и повторять путь, пока данные или условие не скажут стоп.
Программа, которая только хранит значения, ничего не делает. Она становится полезной в тот момент, когда начинает выбирать: если корзина пуста, показать сообщение о пустой корзине; для каждой строки файла прибавить цену. Это и есть единственные два хода, которые есть у программы. Условия выбирают путь. Циклы повторяют путь. Любой алгоритм, который ты когда-нибудь напишешь, собран из этих двух ходов, вложенных друг в друга.
В logic:1 ты писал выражения вида not paid, paid and age >= 18, paid or free. Тогда они были абстрактными. В коде это ровно те же выражения, а if — это машина, которая превращает одно из них в действие.
logic:1 code
not paid --> !paid
paid and age >= 18 --> paid && age >= 18
paid or free --> paid || free
if (paid && age >= 18) { ... }Та же булева алгебра, две записи. Имена операторов меняются, таблицы истинности нет.Вот одно и то же решение на трёх языках: этот человек взрослый?
if age >= 18:
label = "adult"
else:
label = "minor"Python: двоеточие и отступы вместо фигурных скобок.let label;
if (age >= 18) {
label = "adult";
} else {
label = "minor";
}JavaScript: фигурные скобки вокруг тела и точки с запятой в конце.var label string
if age >= 18 {
label = "adult"
} else {
label = "minor"
}Go: фигурные скобки, а условие пишется без круглых скобок.Циклы бывают двух видов, и выбрать правильный — это и есть почти всё умение. Цикл for повторяется по одному разу на каждый элемент известной коллекции, и о том, когда остановиться, решает кто-то другой. Цикл while повторяется, пока условие остаётся истинным, и о том, когда остановиться, решаешь ты, меняя что-то внутри тела.
for item in list: once per item, list decides how many
while needed: while the condition stays true, repeat
for i in range(3): 3 rounds
while retries < 3: up to 3 rounds, or fewer if it succeeds earlyЦикл for считает то, что ему дали. Цикл while считает сам себя и может ошибиться.Один и тот же цикл for на трёх языках: сложить список оценок.
total = 0
for score in scores:
total = total + scorePython: for прямо по списку, индекс не нужен.let total = 0;
for (const score of scores) {
total = total + score;
}JavaScript: for of идёт по значениям, а не по позициям.total := 0
for _, score := range scores {
total = total + score
}Go: range даёт и позицию, и значение, и Go требует, чтобы ты использовал оба.А теперь цикл, который никогда не заканчивается, и почему так выходит. Цикл while повторяется, пока условие истинно. Условие проверяется в начале каждого круга. Если внутри тела ничто никогда не меняет то, что проверяет условие, условие остаётся истинным навсегда, и цикл крутится вечно. Программа не сломана. Она делает ровно то, что ей сказали, честно, пока ты не закроешь вкладку.
while retries < 3:
print("trying")
trying
trying
trying
... and the tab never comes backУсловие retries < 3 истинно на первом круге. Внутри ничто не меняет retries, значит оно истинно и на миллионном.Вспомни Big-O из logic:1: считай шаги как функцию от объёма данных и не думай о том, быстрая ли машина. В цикле этот подсчёт виден лучше всего, потому что цикл по n элементам выполняет своё тело n раз.
for x in list: work * n O(n)
for i in range(n):
for j in range(n): work * n * n O(n^2)
n = 1000 O(n) ~1000 steps
O(n^2) ~1000000 stepsОдин цикл — n кругов. Цикл внутри цикла — n раз по n кругов.Практика
Посмотри на цикл. Чему равно total после его завершения?
Подсказки
- Распиши каждый круг на бумаге: чему равно total до круга и чему оно становится.
- Цикл не выполняется, если условие ложно ещё до первого круга, так что проверь начальное значение.
Вот цикл while, который считает от трёх вниз. Расставь круги в том порядке, в каком они происходят, и закончи моментом остановки цикла.
- 1Проверить условие снова на следующем круге
- 2Выйти из цикла и продолжить со следующей строки программы
- 3Выполнить тело: напечатать n и вычесть единицу из n
- 4Проверить условие n > 0 и увидеть, что оно истинно
- 5Проверить условие и увидеть, что оно ложно, потому что n дошло до 0
Подсказки
- Внутри тела цикла ничто не меняется: одни и те же шаги повторяются, и только один из них меняет ответ.
- Цикл останавливается потому, что условие становится ложным, а ложным оно может стать только если что-то внутри цикла его сдвигает.
Сопоставь каждый кусок кода с тем, как растёт его стоимость при росте данных. Это идея Big-O из logic:1, увиденная изнутри цикла.
Подсказки
- Сравнивай форму роста, а не точное число шагов: одна лишняя строка может дать один лишний круг или n лишних кругов.
- Два вложенных цикла по одному списку перемножаются, а не складываются.