SkillGridИзучай computer science на практике

Управляющий поток: условия и циклы

Всего два хода, которые есть у программы: выбрать путь булевой алгеброй и повторять путь, пока данные или условие не скажут стоп.

13 мин · 42 XP

Программа, которая только хранит значения, ничего не делает. Она становится полезной в тот момент, когда начинает выбирать: если корзина пуста, показать сообщение о пустой корзине; для каждой строки файла прибавить цену. Это и есть единственные два хода, которые есть у программы. Условия выбирают путь. Циклы повторяют путь. Любой алгоритм, который ты когда-нибудь напишешь, собран из этих двух ходов, вложенных друг в друга.

В 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 требует, чтобы ты использовал оба.
totallooptotal = 0+ score 90, total = 90+ score 85, total = 175+ score 77, total = 252the list runs out, the loop stops on its own

А теперь цикл, который никогда не заканчивается, и почему так выходит. Цикл 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 кругов.

Практика

  1. Посмотри на цикл. Чему равно total после его завершения?

    Подсказки
    • Распиши каждый круг на бумаге: чему равно total до круга и чему оно становится.
    • Цикл не выполняется, если условие ложно ещё до первого круга, так что проверь начальное значение.
  2. Вот цикл while, который считает от трёх вниз. Расставь круги в том порядке, в каком они происходят, и закончи моментом остановки цикла.

    1. 1Проверить условие снова на следующем круге
    2. 2Выйти из цикла и продолжить со следующей строки программы
    3. 3Выполнить тело: напечатать n и вычесть единицу из n
    4. 4Проверить условие n > 0 и увидеть, что оно истинно
    5. 5Проверить условие и увидеть, что оно ложно, потому что n дошло до 0
    Подсказки
    • Внутри тела цикла ничто не меняется: одни и те же шаги повторяются, и только один из них меняет ответ.
    • Цикл останавливается потому, что условие становится ложным, а ложным оно может стать только если что-то внутри цикла его сдвигает.
  3. Сопоставь каждый кусок кода с тем, как растёт его стоимость при росте данных. Это идея Big-O из logic:1, увиденная изнутри цикла.

    Подсказки
    • Сравнивай форму роста, а не точное число шагов: одна лишняя строка может дать один лишний круг или n лишних кругов.
    • Два вложенных цикла по одному списку перемножаются, а не складываются.