EduBrick
классная работа

Строка как последовательность

Программирование на Python: от нуля до олимпиад

0/18решено 0 из 18до зачёта осталось 10

Чему научитесь

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

Как устроено занятие

Сначала разбор с примерами и короткими проверками понимания — они нужны, чтобы поймать непонятое сразу, а не через три темы.

Дальше 15 задач лестницей: разминка, основа, со звёздочкой. Занятие засчитывается, когда решено 10 — остальные не пропадают и учитываются отдельно.

После занятия — вторая часть, ещё 15 задач на те же приёмы в новых сюжетах.

Сколько это займёт

Примерно час-полтора вместе с задачами. Сроков нет: можно закрыть вкладку и вернуться когда удобно — прогресс сохранится.

теория

Данные, которые не число

Двенадцать занятий подряд на входе были числа. И всё это время input() возвращал вовсе не число, а строку — просто мы сразу писали int(input()) и превращали её в число.

Теперь превращать не будем:

s = input()          # строка, как есть
print(len(s))        # сколько в ней символов

Строка — это последовательность символов, у каждого из которых есть номер. Нумерация начинается с нуля, как и у range:

строка h e l l o
номер 0 1 2 3 4

Символ по номеру берут квадратными скобками: s[0] — первый, s[4] — последний. Длина здесь 5, а номер последнего — 4: последний символ всегда s[len(s) - 1].

Это единственное новое понятие занятия. Всё остальное — циклы, условия, накопители — вы уже умеете, и они работают со строкой ровно так же, как работали с числами.

теория

Два способа перебрать строку

Перебирать символы можно двумя способами, и выбор между ними — не дело вкуса.

for ch in s:              # даёт сами символы
    if ch == "a":
        count += 1
for i in range(len(s)):   # даёт номера
    if s[i] == "a":
        count += 1

Первый короче и читается лучше. Но в нём нет номера — а он нужен, как только задача про положение или про соседей.

что нужно какой цикл
посчитать символы по условию for ch in s
найти позицию символа for i in range(len(s))
сравнить соседние символы for i in range(1, len(s)) и s[i] с s[i - 1]
пройти с конца for i in range(len(s) - 1, -1, -1)

Третья строка таблицы — знакомый приём: так же вы сравнивали соседние числа в потоке. Цикл начинается с единицы, потому что у самого первого символа предыдущего нет.

тест

Проверка: номера и длина

Строка s равна "python". Какое выражение даст последний символ?

Войдите, чтобы ответить.
теория

Отрицательные номера

Писать s[len(s) - 1] каждый раз, когда нужен последний символ, утомительно. Поэтому в Python есть сокращение:

s = "hello"
print(s[-1])      # o — последний
print(s[-2])      # l — предпоследний

Отрицательный номер отсчитывается с конца: -1 — последний символ, -2 — предыдущий, и так далее. Полностью равнозначно s[len(s) - 1] и s[len(s) - 2].

Это удобство, а не новая возможность: всё то же самое можно писать через длину. Но в задачах про начало и конец строки отрицательные номера заметно короче.

Границы существуют в обе стороны. У строки длиной 5 допустимы номера от -5 до 4. Обращение к s[5] или s[-6] — ошибка, программа остановится с сообщением string index out of range. Это самая частая поломка занятия, и почти всегда причина одна: цикл дошёл до len(s) включительно.

теория

Символы сравниваются

Символы можно сравнивать между собой — <, >, == работают и с ними:

print("a" < "b")     # True: в алфавите a раньше

Отсюда главный приём занятия. Латинские буквы идут подряд, цифры тоже, поэтому проверка «символ — строчная буква» пишется одним условием:

if "a" <= ch <= "z":
    ...

Так же проверяются цифры ("0" <= ch <= "9") и заглавные буквы ("A" <= ch <= "Z"). Двойное сравнение вы уже видели в занятии про условия — здесь оно работает точно так же.

Символ-цифра — не число

"7" и 7 — разные вещи. Первое — символ, второе — число, и складывать их нельзя:

total = 0
for ch in s:
    if "0" <= ch <= "9":
        total += int(ch)      # int превращает символ в число

Без int программа либо упадёт, либо — что хуже — начнёт склеивать строки вместо сложения чисел.

расчёт

Проверка: сколько сравнений

В строке из 10 символов нужно сравнить каждый символ с соседом слева.

Сколько получится сравнений? Введите целое число.

Войдите, чтобы ответить.
теория

Три ошибки этого занятия

Выход за границу. for i in range(len(s) + 1) или обращение к s[i + 1] на последнем шаге. Признак: программа падает с string index out of range. Проверьте, до какого номера доходит цикл: последний допустимый — len(s) - 1.

Символ вместо числа. "5" + 1 — ошибка, "5" + "1" даёт "51", а не 6. Если в строке цифры и нужна арифметика, каждый символ пропускается через int.

Попытка изменить строку. s[0] = "x" не работает: строку в Python поменять нельзя, можно только собрать новую. Поэтому задачи вида «уберите символ» решаются накоплением: заводится пустая строка и к ней по одному прибавляются нужные символы.

result = ""
for ch in s:
    if ch != "a":
        result += ch

Как проверять себя

  • строка из одного символа — ломает всё, где есть «соседи» или «первый и последний»;
  • символа нет вовсе — задача про поиск должна что-то ответить и в этом случае;
  • все символы одинаковые — проверяет строгие сравнения.
теория

Практика: пятнадцать задач

Лестница прежняя: пять разминочных, семь основных, три со звёздочкой. Зачёт при десяти решённых.

Готовых средств для строк в Python много, и дальше мы их разберём. Но в этом занятии всё делается вручную: перебором, сравнением и накоплением. Так становится видно, что происходит внутри, — а метод, вызванный без понимания, потом подводит на первой же нестандартной задаче.

Строки в задачах — латинские буквы, цифры и одиночные пробелы. Русские буквы дальше тоже появятся, но проверка «между a и z» на них не работает, и до кодов символов мы ещё не дошли.

лестница задач
развёрнутый ответ

Программа, которая падает на каждой строке

Задача: «дана строка, посчитайте, сколько в ней пар соседних одинаковых символов».

Ученик написал:

s = input()
count = 0

for i in range(len(s)):
    if s[i] == s[i + 1]:
        count += 1

print(count)

Программа падает с сообщением string index out of range. Объясните, на каком шаге это происходит и почему, и предложите два разных исправления.

Войдите, чтобы ответить.