Чему научитесь
- Доставать из числа любую цифру без превращения его в строку
- Считать сумму, количество и свойства цифр
- Собирать из цифр новое число — перевёрнутое или с вычеркнутыми
- Работать с разрядами через степени десятки
Как устроено занятие
Сначала разбор с примерами и короткими проверками понимания — они нужны, чтобы поймать непонятое сразу, а не через три темы.
Дальше 15 задач лестницей: разминка, основа, со звёздочкой. Занятие засчитывается, когда решено 10 — остальные не пропадают и учитываются отдельно.
После занятия — вторая часть, ещё 15 задач на те же приёмы в новых сюжетах.
Сколько это займёт
Примерно час-полтора вместе с задачами. Сроков нет: можно закрыть вкладку и вернуться когда удобно — прогресс сохранится.
Число как запись
До сих пор число было величиной: его складывали, сравнивали, делили. Сегодня оно становится записью — последовательностью цифр, к которым нужен доступ по отдельности.
Задачи звучат так: сумма цифр, наибольшая цифра, палиндром ли число, сколько в нём двоек. Все они об одном — как добраться до цифры.
Инструментов ровно два, и оба вы уже знаете:
| действие | что даёт | пример |
|---|---|---|
n % 10 |
последнюю цифру | 1234 % 10 → 4 |
n // 10 |
число без последней цифры | 1234 // 10 → 123 |
Первый достаёт цифру, второй сдвигает число, открывая следующую. Больше ничего не нужно.
Позже вы узнаете, что число можно превратить в строку и пройтись по символам. Это тоже рабочий способ, но он прячет от вас разряды — а на них дальше держатся системы счисления и целый класс олимпиадных задач. Поэтому здесь только арифметика.
Основной цикл разбора
Два действия соединяются в цикл, который надо запомнить наизусть — он встретится в каждой задаче занятия:
n = int(input())
s = 0
while n > 0:
digit = n % 10 # взяли последнюю цифру
s += digit # что-то с ней сделали
n //= 10 # отбросили её
print(s)
Проследим на 1234, шаг за шагом:
| шаг | n | digit | s |
|---|---|---|---|
| 1 | 1234 | 4 | 4 |
| 2 | 123 | 3 | 7 |
| 3 | 12 | 2 | 9 |
| 4 | 1 | 1 | 10 |
| — | 0 | — | цикл кончился |
Цифры идут справа налево. Это важно: если задача про первую цифру или про порядок цифр, разбор выдаёт их в обратном порядке, и это надо учитывать, а не игнорировать.
И обратите внимание, что число n по ходу разрушается. Если оно понадобится в конце — например, чтобы сравнить с перевёрнутым, — сохраните его копию до цикла.
Проверка: что будет с нулём
Программа считает количество цифр обычным разбором:
count = 0
while n > 0:
n //= 10
count += 1
Что она выведет при n = 0?
Собрать число обратно
Разобрать — половина дела. Часто нужно построить новое число из цифр: перевернуть запись, выкинуть лишние цифры, оставить только чётные.
Приём зеркальный разбору:
result = result * 10 + digit
Умножение на 10 сдвигает уже собранное на разряд влево, а прибавление ставит новую цифру в освободившееся место. Переворот числа целиком:
n = int(input())
result = 0
while n > 0:
result = result * 10 + n % 10
n //= 10
print(result)
Заметьте, что переворот получился бесплатно: разбор идёт справа налево, сборка — слева направо, и порядок сам собой меняется на обратный.
А вот если нужно сохранить порядок — скажем, вычеркнуть из числа все тройки, — так просто уже не выйдет. Тогда собирают с растущим разрядом:
kept = 0
power = 1
while n > 0:
digit = n % 10
if digit != 3:
kept += digit * power
power *= 10 # разряд растёт только когда цифру оставили
n //= 10
Последняя строка с power — то место, где ошибаются чаще всего: разряд должен расти только для оставленных цифр.
Разряды и степени десятки
Иногда нужна не «очередная» цифра, а конкретная — третья справа, или всё, что стоит левее неё. Здесь работают степени десятки.
| выражение | смысл |
|---|---|
n % 100 |
две последние цифры |
n // 100 |
всё, кроме двух последних |
n // 10 ** k % 10 |
цифра на позиции справа, нумерация с нуля |
Отсюда получается и вычёркивание цифры по позиции — целиком арифметикой, без перебора всех цифр:
left = n // 10 ** (k + 1) # всё слева от цифры
right = n % 10 ** k # всё справа от неё
result = left * 10 ** k + right
Такой приём нужен в задачах вида «вычеркните одну цифру, чтобы число стало наибольшим»: позиций всего девятнадцать даже у числа до , и каждую можно просто перебрать.
Проверка: сумма цифр
Чему равна сумма цифр числа 90807? Введите целое число.
Три ошибки этого занятия
Ноль. Цикл while n > 0 при n = 0 не выполняется ни разу. Для суммы цифр это случайно верно, для количества цифр — уже нет: ответ должен быть 1. Если ноль допустим по условию, обработайте его отдельной строкой.
Потерянный оригинал. Разбор разрушает число: к концу цикла в переменной ноль. Если исходное значение нужно потом — сравнить с перевёрнутым, вывести вместе с ответом, — копия делается до цикла, а не после.
Разряд, растущий не там. При сборке с пропуском цифр power *= 10 должно стоять внутри условия. Снаружи оно оставит дырки: вычеркнутая цифра превратится в ноль вместо того, чтобы исчезнуть.
Как проверять себя
Три входа, которые ловят почти всё:
- 0 — выполняется ли то, что должно;
- однозначное число — не рассчитывает ли программа хотя бы на две цифры;
- число с нулями внутри и на конце, например 1000 или 50805 — не теряются ли они и не портят ли сборку.
Практика: пятнадцать задач
Лестница прежняя: пять разминочных, семь основных, три со звёздочкой. Зачёт при десяти решённых.
Почти во всех задачах внутри один и тот же цикл разбора — меняется только то, что делается с очередной цифрой. Напишите его один раз аккуратно, и дальше пойдёт быстро.
Числа доходят до — это 19 цифр. Никакой особой обработки для них не нужно: целые в Python неограниченные, а цикл разбора всё равно делает не больше двух десятков шагов.
Палиндром, который не работает
Задача: «дано число , определите, читается ли оно одинаково в обе стороны».
Ученик написал:
n = int(input())
result = 0
while n > 0:
result = result * 10 + n % 10
n //= 10
if result == n:
print("YES")
else:
print("NO")
Программа отвечает NO даже для числа 12321. Объясните, что именно происходит, какой ответ она даёт для 0, и как это исправить.