Циклы
Заставляем компьютер повторять. for и range, while, break, счётчик, сумма, максимум и перебор делителей. На этой теме держится вся вторая часть ЕГЭ.
- 1for и range
- 2Счётчик и сумма
- 3Максимум и минимум
- 4while и break
- 5Перебор делителей
- 6Сломай код
- 7Где пригодится на ЕГЭ
for и range
Компьютер силён тем, что не устаёт. Проверить миллион чисел для него обычное дело, а для этого нужен цикл. Цикл for повторяет свои строки для каждого значения из списка:
for i in range(5): print('Повтор номер', i) print('Цикл закончился')
Как в if: после строки цикла двоеточие, тело цикла сдвинуто на 4 пробела. Строка без отступа выполнится один раз, после цикла.
Переменная i по очереди принимает значения, которые выдаёт range. У range три формы:
| Запись | Что даёт |
|---|---|
range(5) | 0, 1, 2, 3, 4 |
range(2, 6) | 2, 3, 4, 5 |
range(10, 0, -2) | 10, 8, 6, 4, 2 |
for i in range(2, 6): print(i)
Главное правило: правая граница не входит. range(2, 6) заканчивается на 5. Чтобы перебрать числа от 1 до 100 включительно, пишут range(1, 101).
Третье число это шаг. Он может быть отрицательным, тогда идём вниз:
for i in range(10, 0, -2): print(i)
Счётчик и сумма
Почти любая задача с циклом устроена одинаково: перебираем числа, проверяем условие и что-то копим. Копят обычно одно из двух.
Счётчик отвечает на вопрос «сколько». До цикла k = 0, в цикле при выполнении условия k += 1.
# сколько чисел от 1 до 100 делятся на 7 k = 0 for n in range(1, 101): if n % 7 == 0: k += 1 print(k)
Сумма отвечает на вопрос «сколько всего». До цикла s = 0, в цикле s += n.
# сумма чётных чисел от 1 до 10 s = 0 for n in range(1, 11): if n % 2 == 0: s += n print(s)
Обрати внимание на три места:
k = 0иs = 0стоят до цикла. Если поставить внутрь, они будут обнуляться на каждом шаге;k += 1иs += nстоят внутриif, у них два отступа: один от цикла, второй от условия;printстоит после цикла, без отступа. Нужен один ответ, а не сто.
Чему равна сумма всех чисел от 1 до 100 включительно?
Сколько чисел от 1 до 1000 включительно делятся на 7 и при этом не делятся на 5?
Максимум и минимум
Третья частая вещь: найти самое большое или самое маленькое. Идея такая: держим в переменной лучшее значение, которое видели до сих пор, и сравниваем с ним каждое новое.
Пример. У какого числа от 1 до 50 самый большой остаток от деления на 13 при условии, что число чётное?
best = -1 # лучший остаток, пока ничего не видели best_n = 0 # число, у которого этот остаток for n in range(1, 51): if n % 2 == 0 and n % 13 > best: best = n % 13 best_n = n print(best_n, best)
Остаток 12 впервые даёт число 12. Позже его даст и 38, но условие > строгое, поэтому запомнилось первое. Если нужно последнее такое число, пиши >=.
Начальное значение должно быть хуже любого возможного. Если ищем максимум, а все числа положительные, хватит -1 или 0. Если не уверен, бери огромное: для минимума 10 ** 20, для максимума -10 ** 20.
Если нужен только сам максимум, без того, на каком числе он получился, в Python есть готовые max и min. Им можно передать числа через запятую:
print(max(3, 17, 8)) print(min(3, 17, 8))
А для перебора по циклу как раз нужен ручной способ выше. Позже, в теме про списки, max станет удобнее.
while и break
for удобен, когда заранее понятно, что перебирать. while повторяет, пока условие верно, и подходит, когда неизвестно, сколько будет шагов.
Классика: разобрать число на цифры. Помнишь из темы 1, что n % 10 это последняя цифра, а n // 10 число без неё? Повторяем это, пока от числа что-то осталось:
n = int(input()) s = 0 while n > 0: s += n % 10 # прибавили последнюю цифру n //= 10 # отрезали её print('Сумма цифр:', s)
Каждый шаг цикла число становится короче на одну цифру, и когда оно станет 0, условие n > 0 перестанет выполняться.
Внутри while что-то обязано менять переменную из условия. Забудешь n //= 10, и n навсегда останется больше нуля. Программа зависнет, на сайте её остановит таймер через 10 секунд.
break: выйти раньше
break сразу прерывает цикл. Его ставят, когда нужно найти первое подходящее и дальше не искать:
# первое число больше 100, которое делится на 17 for n in range(101, 1000): if n % 17 == 0: print(n) break
Ещё частый вариант: while True с break внутри. «Повторяй бесконечно, пока не найдёшь»:
n = 1000 while True: n += 1 if n % 17 == 0 and n % 2 == 1: break print(n)
Чему равна сумма цифр числа 2100?
Найди наименьшее число больше 1000, которое делится на 17 и у которого сумма цифр равна 20.
Подсказка
Цикл в цикле: снаружи for n in range(1001, 10000), внутри m = n и while m > 0. Разбираем на цифры копию m, потому что само n нужно для ответа.
Перебор делителей
На ЕГЭ постоянно спрашивают про делители: сколько их, какие, простое ли число. Делитель числа n это такое d, что n % d == 0. Самый простой способ найти все делители: перебрать d от 1 до n.
n = int(input()) k = 0 for d in range(1, n + 1): if n % d == 0: print(d) k += 1 print('Всего делителей:', k)
Число простое, если у него ровно два делителя: 1 и оно само. Значит, проверка простоты это тот же цикл и k == 2.
# сколько простых чисел от 2 до 100 count = 0 for n in range(2, 101): k = 0 for d in range(1, n + 1): if n % d == 0: k += 1 if k == 2: count += 1 print(count)
Тут цикл внутри цикла. Внешний перебирает числа, внутренний для каждого числа перебирает делители. Обрати внимание: k = 0 стоит внутри внешнего цикла, потому что для каждого нового числа делители считаются заново.
Перебор до n медленный: для чисел в миллионы он не успеет. Есть приём в сто раз быстрее, перебирать только до корня из n. Его разберём в уроке по №25, а для чисел до нескольких тысяч хватает и простого способа.
Сколько простых чисел от 2 до 1000?
У какого числа от 1 до 1000 больше всего делителей? Если таких несколько, нужно наименьшее.
Подсказка
Склей два кода: подсчёт делителей из этого раздела и поиск максимума из раздела 3.
Сломай код
В циклах Python почти не ругается. Ошибки тут тихие: код работает, ответ неверный. Во всех примерах ниже хотели посчитать сумму чисел от 1 до 10, правильный ответ 55.
Граница не вошла
s = 0 for n in range(1, 10): s += n print(s)
Вышло 45: число 10 не вошло, правая граница range не включается. Нужно range(1, 11).
Обнуление внутри цикла
for n in range(1, 11): s = 0 s += n print(s)
Вышло 10: на каждом шаге s обнуляется, и в конце там только последнее число. s = 0 должно стоять до цикла.
print внутри цикла
s = 0 for n in range(1, 11): s += n print(s)
Десять строк вместо одной. Ответ это последняя строка, но на ЕГЭ в длинном выводе легко взять не ту. Убери у print отступ.
Вечный цикл
n = 1 s = 0 while n <= 10: s += n print(s)
Забыли n += 1, и n всегда равно 1. Программа зависнет, через 10 секунд сайт её остановит. Добавь n += 1 внутрь цикла и запусти снова.
Прежде чем запускать цикл на большом диапазоне, запусти на маленьком, где ответ знаешь сам. Сумма от 1 до 10 это 55, делителей у 12 шесть штук. Сошлось, тогда меняй границы.
Где пригодится на ЕГЭ
Циклы нужны почти в каждом номере, где решаем кодом. Главные:
| Номер | Что из темы |
|---|---|
| №5 | перебор N, поиск наименьшего через break или min |
| №15 | перебор x и цикл в цикле по параметру A |
| №2 | перебор всех нулей и единиц вложенными циклами |
| №12 | while, который повторяет замены в строке |
| №14 | while с % k и // k: цифры числа в любой системе |
| №25 | перебор делителей, простые числа |
Посмотри, как разбор числа на цифры превращается в задачу №14. Меняем 10 на любое основание, и цикл выдаёт цифры числа в этой системе:
n = 2026 k = 0 # сколько цифр 2 в троичной записи while n > 0: if n % 3 == 2: k += 1 n //= 3 print(k)
Тот же while, только делим на 3, а не на 10. В уроке по №14 этот приём будет главным.
Код в блоках можно менять и запускать. Если программа работает дольше 10 секунд, сайт её остановит: скорее всего, цикл получился вечным.