Каппес Даниил Олегович

ПРАКТИКУМ PYTHON · ЗАНЯТИЕ 6

Строки: индексы, срезы и методы

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

Чему научимся

Символ по номеру

Чтобы добраться до конкретного символа строки, в квадратных скобках указывают его индекс — номер. Считаются символы с нуля, как и range(n): первый символ — s[0], а не s[1].

s = 'Python'
print(s[0])
print(s[3])

Результат

P
h

Отрицательные индексы отсчитывают с конца: s[-1] — последний символ, s[-2] — предпоследний. Это удобно, когда длина строки заранее неизвестна.

СимволPython
Индекс слева012345
Индекс справа−6−5−4−3−2−1

Обращение по несуществующему индексу — самая частая ошибка новичка. У строки 'Python' шесть символов, и s[17] останавливает программу: IndexError: string index out of range.

6.1

Найти запятую

Дополните приведённый код, используя индексатор, так чтобы он вывел символ запятой.

Код

s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print(s[])
Формат выходных данных
Один символ.
Вывод
,
Подсказка 1

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

Подсказка 2

In 2010, — это восемь символов, значит, запятая стоит на восьмом месте, то есть с индексом 7.

Разбор
  1. I — 0, n — 1, пробел — 2, 2 — 3, 0 — 4, 1 — 5, 0 — 6, запятая — 7.
  2. Значит, s[7].
Решение
s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print(s[7])   # I n _ 2 0 1 0 , — запятая восьмая по счёту, индекс 7

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

6.2

Найти букву w

Дополните приведённый код, используя индексатор, так чтобы он вывел символ w.

Код

s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print(s[])
Формат выходных данных
Один символ.
Вывод
w
Подсказка 1

Буква w встречается в строке один раз — в слове two.

Подсказка 2

Считать символы вручную долго и легко ошибиться. Пусть их считает сам Python: длина строки известна, а до конца от w — ровно десять символов.

Разбор
  1. От конца строки удобнее: ...two pizzas. — после w идёт o pizzas., это девять символов.
  2. Значит, w — десятый с конца: s[-10]. Слева это индекс 39.
Решение
s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print(s[-10])   # десятый символ с конца; то же самое, что s[39]

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

Перебор строки циклом

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

s = 'abcdef'
for i in range(len(s)):
    print(s[i])

len(s) — длина строки, значит, range(len(s)) даёт все допустимые индексы: от 0 до длины минус один. Этот способ нужен, когда важен сам номер символа.

Второй — тот самый, с третьего занятия: переменная цикла принимает значения самих символов.

s = 'abcdef'
for c in s:
    print(c)

Разница в том, что известно внутри цикла. В первом случае у нас есть номер i — а значит, и соседний символ s[i - 1], и возможность идти через один. Во втором есть только сам символ.

Правило простое: нужен только символ — перебирайте символы; нужен номер (или соседний символ) — перебирайте индексы.

6.3

Через один

На вход подаётся одна строка. Напишите программу, которая выводит символы строки с индексами 0, 2, 4, … в столбик.

Формат входных данных
Одна строка.
Формат выходных данных
Символы с чётными индексами, каждый на отдельной строке.
Ввод
abcdef
Вывод
a
c
e
Подсказка 1

Здесь важен именно номер символа — значит, перебирать надо индексы.

Подсказка 2

У range() есть третий параметр — шаг.

Разбор
  1. Индексы нужны через один: 0, 2, 4, …
  2. range(0, len(s), 2) даёт ровно их.
  3. Печатаем s[i] на каждом шаге.
Решение
s = input()

for i in range(0, len(s), 2):   # шаг 2 — берём каждый второй индекс
    print(s[i])

Можно было бы перебирать все индексы и проверять i % 2 == 0, но шаг у range() делает это без всякой развилки. Заодно видно, зачем нужен перебор по индексам: по символам номер узнать было бы неоткуда.

6.4

Сумма цифр строки

На вход подаётся одна строка, состоящая из цифр. Напишите программу, которая считает сумму цифр этой строки.

Формат входных данных
Строка из цифр.
Формат выходных данных
Одно число — сумма цифр.
Ввод
2514
Вывод
12
Подсказка 1

Номера символов здесь не нужны — только сами символы.

Подсказка 2

Символ '5' — это текст, а не число; сложить его с числом нельзя, пока не переведёте int().

Разбор
  1. Обнуляем накопитель.
  2. Перебираем символы строки.
  3. Каждый переводим в число и прибавляем.
Решение
s = input()

total = 0
for c in s:
    total += int(c)   # символ '5' — это текст, его надо перевести в число

print(total)

int() тут применяется к одному символу, а не ко всей строке. Разница видна на примере: int('2514') — это число 2514, а сумма цифр — 12.

6.5

Есть ли цифра

На вход подаётся одна строка. Напишите программу, которая выводит «Цифра», если строка содержит хотя бы одну цифру, и «Цифр нет» в противном случае.

Пригодится проверка вида c in '0123456789'.

Формат входных данных
Одна строка.
Формат выходных данных
Цифра или Цифр нет.
Ввод 1
Hi Python
Вывод 1
Цифр нет
Ввод 2
Hi 17 Python
Вывод 2
Цифра
Подсказка 1

Ответ известен, как только встретилась первая цифра, — дальше можно не искать.

Подсказка 2

Нужен флажок: до цикла «не нашли», внутри — поднять и выйти по break.

Разбор
  1. Ставим found = False.
  2. Перебираем символы; если символ входит в строку из цифр — поднимаем флажок и прерываем цикл.
  3. После цикла печатаем ответ по флажку.
Решение
s = input()

found = False
for c in s:
    if c in '0123456789':   # символ — одна из цифр
        found = True
        break               # ответ уже известен

if found:
    print('Цифра')
else:
    print('Цифр нет')

Проверка c in '0123456789' — это оператор принадлежности из третьего занятия: он ищет подстроку. Строка из десяти цифр здесь играет роль списка допустимых символов.

6.6

Одинаковые соседи

На вход подаётся одна строка. Напишите программу, которая определяет, сколько в ней пар одинаковых соседних символов.

Формат входных данных
Одна строка.
Формат выходных данных
Одно число — количество совпадений.
Ввод 1
abcd
Вывод 1
0
Ввод 2
aabbcc
Вывод 2
3
Ввод 3
aaa
Вывод 3
2
Подсказка 1

Сравнивать надо символ с соседним — значит, без индексов не обойтись.

Подсказка 2

Если начать перебор с индекса 1, то у каждого символа заведомо есть предыдущий.

Разбор
  1. Заводим счётчик.
  2. Перебираем индексы от 1 до конца строки.
  3. Сравниваем s[i] с s[i - 1] и считаем совпадения.
Решение
s = input()

count = 0
for i in range(1, len(s)):   # начинаем с единицы: у s[0] нет предыдущего
    if s[i] == s[i - 1]:
        count += 1

print(count)

Начать перебор с нуля и писать s[i + 1] тоже можно, но тогда цикл должен закончиться на len(s) - 1, иначе последний шаг выйдет за конец строки и программа упадёт с IndexError. Вариант «смотреть назад» такой ошибки не допускает вовсе.

Срезы

Срез (slice) вырезает из строки целый кусок. Записывается он как два индекса через двоеточие: s[x:y] — от x включительно до y не включительно. То же правило, что и у range().

s = 'abcdefghij'
print(s[2:5])
print(s[0:6])

Результат

cde
abcdef

Любую границу можно опустить. s[x:] — от x до конца, s[:y] — от начала до y, а s[:] — вся строка целиком.

print(s[2:])
print(s[:7])

Результат

cdefghij
abcdefg

Работают и отрицательные индексы — счёт с конца сохраняется:

print(s[-9:-4])
print(s[-3:])

Результат

bcdef
hij

У среза есть и третий параметр — шаг, как у range(). Отрицательный шаг разворачивает строку задом наперёд:

print(s[::2])
print(s[::-1])

Результат

acegi
jihgfedcba

Строки неизменяемы. Поменять символ по индексу нельзя — s[4] = 'X' остановит программу. Новую строку собирают из срезов:

s = 'abcdefghij'
s = s[:4] + 'X' + s[5:]
print(s)

Результат

abcdXfghij

Удалить последний символ проще всего срезом s[:-1]. А если первая граница среза больше второй, получится пустая строка — ошибки не будет.

6.7

Что напечатает срез

Проверьте с помощью интерпретатора, что покажет приведённый код. Затем исправьте его так, чтобы в консоль выводилось bcdef.

Код

s = 'abcdefg'
print(s[2:5])
Формат выходных данных
Одна строка.
Вывод
bcdef
Подсказка 1

Исходный код печатает cde: срез начинается с индекса 2 и заканчивается перед индексом 5.

Подсказка 2

Нужное bcdef начинается с b — это индекс 1, а заканчивается на f — это индекс 5, значит, правая граница на единицу больше.

Разбор
  1. b стоит под индексом 1 — это левая граница.
  2. f стоит под индексом 5, но правая граница не включается, поэтому пишем 6.
Решение
s = 'abcdefg'
print(s[1:6])   # от b включительно до g не включительно

Правило «правая граница не включается» проще запомнить через длину: в срезе s[1:6] ровно 6 − 1 = 5 символов. Так и проверяют себя: разность границ — это длина куска.

6.8

Срез от начала

Проверьте, что покажет приведённый код, и исправьте его так, чтобы выводилось abcd.

Код

s = 'abcdefg'
print(s[:3])
Формат выходных данных
Одна строка.
Вывод
abcd
Подсказка 1

Исходный код печатает abc — три символа.

Подсказка 2

Нужно четыре.

Разбор
  1. Левая граница опущена — срез идёт от начала.
  2. Правая граница равна нужному количеству символов: четыре.
Решение
s = 'abcdefg'
print(s[:4])   # первые четыре символа

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

6.9

Срез с отрицательным шагом

Проверьте, что покажет приведённый код, и исправьте его так, чтобы выводилось gfedcb.

Код

s = 'abcdefg'
print(s[::-3])
Формат выходных данных
Одна строка.
Вывод
gfedcb
Подсказка 1

Исходный код печатает gda: идёт с конца и берёт каждый третий символ.

Подсказка 2

Нужны все символы подряд, кроме самого первого. Значит, шаг должен стать −1, а срез — останавливаться перед a.

Разбор
  1. Шаг −1 разворачивает строку: получилось бы gfedcba.
  2. Лишняя a — это символ с индексом 0, и её надо отбросить.
  3. Правая граница 0 не включается, поэтому s[:0:-1] даёт ровно gfedcb.
Решение
s = 'abcdefg'
print(s[:0:-1])   # разворот, но без символа с индексом 0

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

6.10

Первые 12 символов

Дополните приведённый код, используя срезы, так чтобы он вывел первые 12 символов строки s.

Код

s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print()
Формат выходных данных
Одна строка.
Вывод
In 2010, som
Подсказка 1

Левую границу можно опустить — срез начнётся с начала строки.

Подсказка 2

Правая граница здесь и есть количество символов.

Разбор
  1. Пишем срез от начала до 12: s[:12].
Решение
s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print(s[:12])

Обратите внимание на результат: In 2010, som — срез не смотрит на слова и режет строку ровно по счёту символов.

6.11

Последние 9 символов

Дополните приведённый код, используя срезы, так чтобы он вывел последние 9 символов строки s.

Код

s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print()
Формат выходных данных
Одна строка.
Вывод
o pizzas.
Подсказка 1

Отрицательный индекс отсчитывает с конца.

Подсказка 2

Правую границу можно опустить — срез дойдёт до конца строки.

Разбор
  1. Девятый символ с конца — это индекс −9.
  2. Срез s[-9:] идёт от него до конца.
Решение
s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print(s[-9:])

Длину строки при этом знать не нужно вовсе — в этом и смысл отрицательных индексов. Программа будет работать с любой строкой длиннее девяти символов.

6.12

Задом наперёд

Дополните приведённый код, используя срезы, так чтобы он вывел строку s в обратном порядке.

Код

s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print(s[])
Формат выходных данных
Одна строка.
Вывод
.sazzip owt rof nioctiB k01 diap enoemos ,0102 nI
Подсказка 1

Обе границы опускаются: нужна вся строка.

Подсказка 2

А разворачивает её отрицательный шаг.

Разбор
  1. Пишем срез без границ, но с шагом −1: s[::-1].
Решение
s = 'In 2010, someone paid 10k Bitcoin for two pizzas.'
print(s[::-1])

s[::-1] — самый известный срез в Python. Им же проверяют палиндромы: слово читается одинаково в обе стороны, если s == s[::-1].

6.13

Половинки местами

На вход подаётся строка текста. Напишите программу, которая разрежет её на две равные части, переставит их местами и выведет на экран.

Если длина строки нечётная, первая часть должна быть на один символ длиннее. Пригодятся // и %.

Формат входных данных
Одна строка.
Формат выходных данных
Та же строка с переставленными половинами.
Ввод 1
abcdef
Вывод 1
defabc
Ввод 2
abcdefg
Вывод 2
efgabcd
Ввод 3
a
Вывод 3
a
Подсказка 1

Место разреза — это длина первой части. При чётной длине она равна половине, при нечётной — на единицу больше.

Подсказка 2

len(s) // 2 + len(s) % 2 даёт нужное число сразу для обоих случаев.

Разбор
  1. Считаем место разреза: half = len(s) // 2 + len(s) % 2.
  2. Первая часть — s[:half], вторая — s[half:].
  3. Печатаем их в обратном порядке, склеив конкатенацией.
Решение
s = input()

# при нечётной длине остаток даёт лишний символ первой половине
half = len(s) // 2 + len(s) % 2

print(s[half:] + s[:half])

Проверьте себя на строке из одного символа: half равен 1, первый срез пустой, второй — вся строка, и ответ верный. Пустой срез не ошибка, и именно поэтому такой код не нуждается в отдельной развилке для коротких строк.

Методы: функции, привязанные к объекту

Метод — это функция, применяемая к объекту. Пишется он через точку: имя_объекта.имя_метода(параметры). Например, s.find('e') — это применение к строке s метода find с параметром 'e'.

Строковые методы делятся на три группы: изменение регистра, поиск и замена, классификация символов. Первые две — в этом занятии, третья — в следующем.

МетодЧто делаетПример
lower()все буквы в нижний регистр'FoO'.lower()foo
upper()все буквы в верхний регистр'FoO'.upper()FOO
capitalize()первая буква заглавная, остальные строчные'foO BaR'.capitalize()Foo bar
title()первая буква каждого слова — заглавная'the sun'.title()The Sun
swapcase()меняет регистр каждой буквы на противоположный'FoO'.swapcase()fOo

Методы не меняют исходную строку — строки неизменяемы. Они возвращают новую. Если строку надо изменить, результат присваивают обратно: s = s.lower().

У title() алгоритм простой и не всегда умный: он не различает важные и неважные слова и спотыкается об апострофы. "what's happened to ted's IBM stock?".title() даёт What'S Happened To Ted'S Ibm Stock?.

6.14

Имя и фамилия с заглавной

На вход подаётся строка, состоящая из имени и фамилии человека, разделённых одним пробелом. Напишите программу, которая проверяет, что и имя, и фамилия начинаются с заглавной буквы.

Формат входных данных
Одна строка: имя и фамилия через пробел.
Формат выходных данных
YES или NO.
Ввод 1
chris alan
Вывод 1
NO
Ввод 2
Chris Alan
Вывод 2
YES
Ввод 3
Chris alan
Вывод 3
NO
Подсказка 1

Первая буква имени — это s[0]. А как добраться до первой буквы фамилии, не зная длины имени?

Подсказка 2

Найдите пробел методом find() — фамилия начинается сразу за ним.

Разбор
  1. s.find(' ') возвращает индекс пробела.
  2. Первая буква фамилии стоит следом: s[space + 1].
  3. Буква заглавная, если она совпадает со своей же заглавной версией: c == c.upper().
  4. Обе проверки обязательны — соединяем через and.
Решение
s = input()

space = s.find(' ')      # где заканчивается имя
first = s[0]             # первая буква имени
second = s[space + 1]    # первая буква фамилии

if first == first.upper() and second == second.upper():
    print('YES')
else:
    print('NO')

Метод title() тут не годится, хотя и кажется подходящим: он ещё и приводит остальные буквы к строчным, и запись «CHRIS ALAN» он объявил бы неверной. Проверять надо ровно то, о чём спрашивают, — первые буквы.

6.15

Хороший оттенок

На вход подаётся строка текста. Напишите программу, которая определяет, хороший ли у текста оттенок. Текст имеет хороший оттенок, если содержит подстроку «хорош» в любом регистре.

Формат входных данных
Одна строка.
Формат выходных данных
YES или NO.
Ввод 1
я очень хороший текст =)
Вывод 1
YES
Ввод 2
оыралоывало ХОРОШвмсва выарлво83кг834
Вывод 2
YES
Ввод 3
Цвет настроения синий
Вывод 3
NO
Подсказка 1

Оператор in различает регистр, поэтому «ХОРОШ» он не найдёт.

Подсказка 2

Приведите всю строку к одному регистру — и искать станет нечего.

Разбор
  1. Переводим строку в нижний регистр методом lower().
  2. Ищем в результате подстроку «хорош» оператором in.
Решение
s = input()

# приводим к одному регистру, чтобы «ХОРОШ» и «Хорош» тоже нашлись
if 'хорош' in s.lower():
    print('YES')
else:
    print('NO')

Приём «привести к одному регистру перед сравнением» — стандартный. Важно только не перепутать: искомое слово тоже должно быть в нижнем регистре, иначе не найдётся уже ничего.

6.16

Сколько строчных букв

На вход подаётся строка. Напишите программу, которая подсчитывает количество буквенных символов в нижнем регистре.

Попробуйте использовать проверку на неравенство != в сочетании с одним из строковых методов.

Формат входных данных
Одна строка.
Формат выходных данных
Одно число.
Ввод 1
abcABCD12345
Вывод 1
3
Ввод 2
Привет, Мир!
Вывод 2
7
Подсказка 1

Цифры и знаки препинания считать не нужно — только буквы.

Подсказка 2

У цифры и запятой заглавной версии нет: ','.upper() — это по-прежнему запятая. А вот у строчной буквы она есть и отличается от неё самой.

Разбор
  1. Перебираем символы строки.
  2. Символ — строчная буква, если он не равен своей же заглавной версии.
  3. Считаем такие символы.
Решение
s = input()

count = 0
for c in s:
    if c != c.upper():   # у цифр и знаков upper() ничего не меняет
        count += 1

print(count)

Эта проверка одним движением отсеивает и заглавные буквы, и всё небуквенное. На следующем занятии появится метод islower(), и условие станет ещё короче — но приём с upper() стоит понять: он показывает, что «буква» и «не буква» различаются по поведению, а не по внешнему виду.

Поиск и замена

МетодЧто делает
count(sub)сколько раз подстрока встречается в строке (без наложений)
find(sub)индекс первого вхождения; если не нашлось — −1
rfind(sub)то же, но поиск с конца
index(sub)как find(), но при неудаче останавливает программу ошибкой
startswith(sub)начинается ли строка с подстроки — True или False
endswith(sub)заканчивается ли строка подстрокой
strip()убирает пробелы в начале и в конце строки
lstrip() / rstrip()то же, но только слева или только справа
replace(old, new)заменяет все вхождения одной подстроки на другую
s = 'foo bar foo baz foo qux'
print(s.count('foo'))
print(s.find('bar'))
print(s.find('python'))
print(s.replace('foo', 'grault', 2))

Результат

3
4
-1
grault bar grault baz foo qux

У replace() есть необязательный третий параметр — сколько замен сделать. У методов поиска — необязательные start и end: они ограничивают поиск куском строки, ровно как срез. А strip(), lstrip() и rstrip() принимают необязательный набор символов: без него они убирают пробелы, а с ним — всё, что в нём перечислено.

print('  Python  '.strip())
print('***Python***'.strip('*'))
print('www.python.org'.strip('wor.'))

Результат

Python
Python
python

find() и rfind() безопаснее, чем index() и rindex(): не найдя подстроку, они возвращают −1, а не останавливают программу с ошибкой ValueError.

6.17

Сколько слов

На вход подаётся строка текста, состоящая из слов, разделённых ровно одним пробелом. Напишите программу, которая подсчитывает количество слов в ней.

Формат входных данных
Одна строка со словами через пробел.
Формат выходных данных
Одно число — количество слов.
Ввод 1
In 2010, someone paid 10k Bitcoin for two pizzas.
Вывод 1
9
Ввод 2
Привет
Вывод 2
1
Подсказка 1

Считать сами слова не нужно — достаточно посчитать промежутки между ними.

Подсказка 2

Слов всегда на одно больше, чем пробелов.

Разбор
  1. s.count(' ') даёт число пробелов.
  2. Прибавляем единицу — получаем число слов.
Решение
s = input()

# слов на одно больше, чем разделяющих их пробелов
print(s.count(' ') + 1)

Приём работает ровно при условии из задачи: пробел между словами один и лишних нет. На восьмом занятии появится метод split(), который разбирает строку на слова по-настоящему — и справляется с двойными пробелами.

6.18

Генетический код

На вход подаётся строка генетического кода из букв А (аденин), Г (гуанин), Ц (цитозин), Т (тимин). Напишите программу, которая подсчитывает, сколько каждого из них входит в данную строку. Регистр значения не имеет.

Формат входных данных
Одна строка из букв А, Г, Ц, Т в любом регистре.
Формат выходных данных
Четыре строки с подписями.
Ввод 1
АааГГЦЦцТТттт
Вывод 1
Аденин: 3
Гуанин: 2
Цитозин: 3
Тимин: 5
Ввод 2
ааггццттААГГЦЦТТ
Вывод 2
Аденин: 4
Гуанин: 4
Цитозин: 4
Тимин: 4
Подсказка 1

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

Подсказка 2

Дальше каждая из четырёх букв считается методом count().

Разбор
  1. Читаем строку и сразу переводим её в верхний регистр.
  2. Четыре раза применяем count() — по букве на каждое основание.
  3. Печатаем с подписями.
Решение
s = input().upper()   # считаем строчные и заглавные вместе

print('Аденин:', s.count('А'))
print('Гуанин:', s.count('Г'))
print('Цитозин:', s.count('Ц'))
print('Тимин:', s.count('Т'))

.upper() применён прямо к результату input() — отдельная строка для этого не нужна. Заодно исчезает шанс забыть про регистр в одном из четырёх подсчётов.

6.19

Сколько цифр

На вход подаётся строка текста. Напишите программу, которая подсчитывает количество цифр в данной строке.

Попробуйте решить задачу с помощью цикла for и строкового метода count().

Формат входных данных
Одна строка.
Формат выходных данных
Одно число — количество цифр.
Ввод 1
l33t 3301
Вывод 1
6
Ввод 2
Python
Вывод 2
0
Подсказка 1

Цифр всего десять, и каждую можно посчитать методом count().

Подсказка 2

Перебирать при этом надо не строку, а сами цифры — по ним и идёт цикл.

Разбор
  1. Заводим накопитель.
  2. Перебираем символы строки '0123456789'.
  3. Для каждой цифры прибавляем к накопителю, сколько раз она встретилась во введённой строке.
Решение
s = input()

count = 0
for d in '0123456789':   # цикл идёт по цифрам, а не по строке
    count += s.count(d)

print(count)

Здесь цикл перебирает не то, что кажется: шагов ровно десять, независимо от длины введённой строки. Обратный вариант — перебирать строку и проверять c in '0123456789' — тоже верен; выбирайте тот, который вам понятнее.

6.20

Адрес сайта

На вход подаётся строка текста. Напишите программу, которая проверяет, что строка заканчивается подстрокой .com или .ru.

Формат входных данных
Одна строка.
Формат выходных данных
YES или NO.
Ввод 1
www.stepik.org
Вывод 1
NO
Ввод 2
www.google.com
Вывод 2
YES
Ввод 3
zeriko-sensei.ru
Вывод 3
YES
Подсказка 1

Для проверки окончания есть готовый метод.

Подсказка 2

Годится любое из двух окончаний — значит, or.

Разбор
  1. s.endswith('.com') — заканчивается ли строка на .com.
  2. То же для .ru.
  3. Соединяем через or.
Решение
s = input()

if s.endswith('.com') or s.endswith('.ru'):
    print('YES')
else:
    print('NO')

Через срезы это же пишется как s[-4:] == '.com', и работает не хуже. Метод короче и, главное, не требует считать длину окончания — ошибиться в четвёрке проще, чем кажется.

6.21

Самый частый символ

На вход подаётся строка текста. Напишите программу, которая выводит символ, встречающийся в ней чаще всего.

Формат входных данных
Одна строка.
Формат выходных данных
Один символ.
Ввод 1
aaaabbc
Вывод 1
a
Ввод 2
abaabbcccc
Вывод 2
c
Подсказка 1

Это поиск максимума, только сравниваются не сами символы, а их количества.

Подсказка 2

Количество каждого символа считает count(), а «лучший на данный момент» хранится в отдельной переменной.

Разбор
  1. Берём первый символ строки как первого претендента.
  2. Перебираем все символы; если очередной встречается чаще, чем нынешний претендент, — заменяем.
  3. После цикла печатаем претендента.
Решение
s = input()

best = s[0]                       # первый претендент
for c in s:
    if s.count(c) > s.count(best):
        best = c

print(best)

Это тот же поиск наибольшего, что и в четвёртом занятии, только «больше» означает «чаще». Начальное значение взято не с потолка, а из самой строки — приём надёжнее выдуманного -1, и работает на любых данных.

Итог занятия

Главное с шестого занятия. Символы строки нумеруются с нуля, а отрицательные индексы считают с конца. Срез s[x:y] берёт кусок, не включая правую границу; третий параметр задаёт шаг, а s[::-1] разворачивает строку. Строки неизменяемы: методы и срезы возвращают новую строку, а исходная остаётся прежней — поэтому результат почти всегда нужно куда-то присвоить или сразу напечатать.