Срезы

Со списками, так же как и со строками, можно делать срезы. А именно:

A[i:j] срез из j-i элементов A[i], A[i+1], ..., A[j-1].

A[i:j:-1] срез из i-j элементов A[i], A[i-1], ..., A[j+1] (то есть меняется порядок элементов).

A[i:j:k] срез с шагом k: A[i], A[i+k], A[i+2*k],... . Если значение k<0, то элементы идут в противоположном порядке.

Каждое из чисел i или j может отсутствовать, что означает «начало строки» или «конец строки»

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

A = [1, 2, 3, 4, 5]
A[2:4] = [7, 8, 9]

Получится список, у которого вместо двух элементов среза A[2:4] вставлен новый список уже из трех элементов. Теперь список стал равен [1, 2, 7, 8, 9, 5].

A = [1, 2, 3, 4, 5, 6,  7]
A[::-2] = [10, 20, 30, 40]

Получится список [40, 2, 30, 4, 20, 6, 10]. Здесь A[::-2] — это список из элементов A[-1], A[-3], A[-5], A[-7], которым присваиваются значения 10, 20, 30, 40 соответственно.

Если не непрерывному срезу (то есть срезу с шагом k, отличному от 1), присвоить новое значение, то количество элементов в старом и новом срезе обязательно должно совпадать, в противном случае произойдет ошибка ValueError.

Обратите внимание, A[i] — это элемент списка, а не срез!

Упражнения

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

В этом же листке, наоборот, нельзя использовать циклы. Используйте срезы и методы.

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

Если программа решается в одну строку, то необходимо использовать функции внутри функций. Например, вот так можно вычислить сумму всех чисел, введенных в строку, используя стандартную функцию sum:

print(sum(map(int, input().split())))

Обратите внимание, в однострочном решении нельзя сохранять список в переменной - нужно сразу же его обработать и вывести результат.

Решение в две строки, как правило, должно иметь следующий вид:

A = input().split()
print(' '.join(...))

При этом зачастую не требуется преобразовывать элементы списка к типу int.

Решение в три строки, как правило, должно иметь следующий вид:

A = input().split()
A = ...
print(' '.join(map(str, ...)))

A: Четные индексы

Выведите все элементы списка с четными индексами

Решите эту задачу в одну строку

1 2 3 4 5
1 3 5
IDE

Генераторы списков — 2

Если каждый элемент списка определяется по достаточно простой формуле (или выражается достаточно простым образом через элементы другого списка), то для его создания удобно использовать генераторы списков (list comprehension): выражения, позволяющие заполнить список некоторой формулой.
Общий вид генератора следующий:

[ выражение for переменная in что-то_итерируемое]
Также генератор может быть усложнён, если добавить дополнительное условие:
[ выражение for переменная in что-то_итерируемое if что_проверить]

Здесь переменная — идентификатор некоторой переменной; что-то_итерируемое — итерируемый объект, из которого извлекаются значения (например, список или range); выражение — некоторое выражение, которым будут заполнены элементы списка, как правило, зависящее от использованной в генераторе переменной; что_проверить — необязательное условие, выполнение которого необходимо для того, элемент был добавлен.

Например, если нужно выбрать все числа, делящиеся на 7 в некотором списке, то это можно сделать так:

my_list = [10, 53, 14, 53, 88, 43, 89, 84, 41, 21, 25, 25, 63, 74, 50, 72, 18, 57, 59, 92]
nums_0_mod_7 = [x for x in my_list if x % 7 == 0]
# Если нужно их сразу вывести:
print(' '.join([str(x) for x in my_list if x % 7 == 0]))

Кстати, каждая строка является итерируемым объектом, который по очереди возвращает свои цифры. Сумму квадратов цифр числа можно найти так:

my_num = 549523521596
sum_dig_sq = sum([int(d)**2 for d in str(my_num)])

B: Четные элементы

Выведите все четные элементы списка.

Решите эту задачу в одну строку

1 2 2 3 3 3 4
2 2 4
IDE

Суммируем логические выражения

В питоне True и False можно использовать как числа в арифметических выражениях. Истина равна единице, а ложь — нулю. Это позволяет писать кратко некоторые вещи. Например, пусть у нас есть числа a, b, c, и мы хотим узнать, сколько из них больше нуля. Вместо громоздкой конструкции

res = 0
if a > 0:
    res += 1
if b > 0:
    res += 1
if c > 0:
    res += 1
можно написать коротко
res = (a > 0) + (b > 0) + (c > 0)

Вместе с генератором списка эта возможность позволяет подсчитывать количество «хороших» элементов в списке в одну строчку. Например, можно так можно посчитать количество чисел от 1 до 9999, в десятичной записи которых есть цифра 7:

print(sum(['7' in str(i) for i in range(1, 10000)]))

Как это работает? Конструкция '7' in str(i) возвращает True, если цифра 7 есть в записи числа i, и False иначе. При этом число i пробегает все значения от 1 до 9999: ('7' in str(i) for i in range(1, 10000)). И наконец функция sum вычисляет сумму всех этих выражений. Так как False равен 0, то сумма равна в точности количеству чисел от 1 до 9999, в десятичной записи которых есть цифра 7.
Развёрнутый код для этой конструкции получается таким:

nums_with_7 = 0
for i in range(1, 10000):
    str_i = str(i)
    if '7' in str_i:
        nums_with_7 += 1
print(nums_with_7)

C: Количество положительных

Найдите количество положительных элементов в данном списке.

Решите эту задачу в одну строку

1 -2 3 -4 5
3
IDE

Операции со списками

Со списками можно легко делать много разных операций.

x in A Проверить, содержится ли элемент в списке. Возвращает True или False
x not in A То же самое, что not(x in A)
min(A) Наименьший элемент списка
max(A) Наибольший элемент списка
A.index(x) Индекс первого вхождения элемента x в список, при его отсутствии генерирует исключение ValueError
A.count(x) Количество вхождений элемента x в список
A.append(x) Добавить в конец списка A элемент x.
A.insert(i, x) Вставить в список A элемент x на позицию с индексом i. Элементы списка A, которые до вставки имели индексы i и больше сдвигаются вправо.
A.extend(B) Добавить в конец списка A содержимое списка B.
A.pop() Удалить из списка последний элемент, возвращается значение удаленного элемента
A.pop(i) Удалить из списка элемент с индексом i, возвращается значение удаленного элемента. Все элементы, стоящие правее удаленного, сдвигаются влево.

F: Наибольший элемент

Решите эту задачу в две строки

1 2 3 2 1
3 2
IDE

H: Наименьший положительный

Выведите значение наименьшего из всех положительных элементов в списке. Известно, что в списке есть хотя бы один положительный элемент.

Решите эту задачу в одну строчку.

5 -4 3 -2 1
1
IDE

M: Вывести в обратном порядке

Решите эту задачу в одну строку. (Требуется только вывести входные числа в обратном порядке, а не переставлять элементы списка.)

1 2 3 4 5
5 4 3 2 1
IDE

N: Переставить соседние

Решите эту задачу в три строки

1 2 3 4 5
2 1 4 3 5

Подсказка:

A = list(range(10))         # -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A[3:8:2] = ['a', 'b', 'c']  # -> [0, 1, 2, 'a', 4, 'b', 6, 'c', 8, 9]
IDE

Q: Циклический сдвиг вправо

Решите эту задачу в две строки. Требуется только вывести циклический сдвиг входных данных, а не переставлять список.

1 2 3 4 5
5 1 2 3 4
IDE

X: Числа k-боначчи

Решите эту задачу в пять строк.

Первая строка — считывание данных. Вторая строка — создание списка. Третья строка — цикл for. Четвертая строка — добавление нового элемента в список. Пятая строка — вывод результата. Для суммирования среза списка используйте функцию sum.

3 6
17
100 0
1
IDE

Y: Кузнечики

Решите эту задачу в четыре строки

Первая строка — считывание списка. Вторая строка — цикл for и считывание числа повторений. Третья строка — модификация списка в цикле. Четвертая строка — вывод результата.

1 2 3 4 2 2
4 1 2 2 3
IDE

Проверки all и any

Иногда бывает нужно проверить, если в списке хотя бы один какой-нибудь «особый» элемент. Или проверить, что все элементы списка «хорошие». Команды all и any позволяют сделать это в одну строчку. Итак, если имеется какой-нибудь итерируемый объект (например, список), то выражение

all(условие for объект in что-то_итерируемое)

принимает значение True если и только если, условие выполнено для всех объектов в что-то_итерируемое.

any(условие for объект in что-то_итерируемое)
принимает значение True если и только если, условие выполнено хотя бы для одного объекта в что-то_итерируемое.

Например, проверим, что все числа в списке (или хотя бы одно) находятся в диапазоне от 1000 до 9999:

if all(1000 <= x <= 9999 for x in my_list):
    print('Все элементы от 1000 до 9999')
if any(1000 <= x <= 9999 for x in my_list):
    print('По крайней мере один элемент от 1000 до 9999')
Развёрнутый код для каждой из конструкций:
bad_found = False
for x in my_list:
    if not 1000 <= x <= 9999:
        bad_found = True
        break
if not bad_found:
    print('Все элементы от 1000 до 9999')
#
good_found = False
for x in my_list:
    if 1000 <= x <= 9999:
        good_found = True
        break
if good_found:
    print('По крайней мере один элемент от 1000 до 9999')

Тернарный оператор условия

В языке питон есть тернарная условная операция, подобная [expression]?[on_true]:[on_false] в языке си. Тернарная условная операция принимает на вход три параметра: логическое выражение и два значения, и возвращает первое или второе значение в зависимости от значения логического выражения. Его синтаксис такой:

[on_true] if [expression] else [on_false]
>>> 'equal' if 1 == 1 else 'not equal'
'equal'
>>> 'equal' if 1 == 2 else 'not equal'
'not equal'

Данную конструкцию можно вкладывать в себя:

res = 'foo' if x == 1 else 'boo' if x == 2 else 'zoo' if x == 3 else 'goo'

Ситуация, когда тернарный оператор прямо уместен, встречается не так часто. Однако в генераторах списков, в all и в any он может быть удобен.

ZA: Числа с 0 в десятичной записи

На вход даётся натуральное число $N < 1000000$. Выведите количество чисел от 1 до $N$, в десятичной записи которых есть цифра 0.

Решите эту задачу в одну строчку

9
0
10
1
1000
181
IDE

ZB: Количество нулей в десятичной записи

На вход даётся натуральное число $N < 1000000$. Выведите количество цифр 0, которые встречаются в десятичной записи чисел от 1 до $N$.

Решите эту задачу в одну строчку

9
0
10
1
1000
192
IDE

ZC: Счастливые билеты

Билет с шестизначным номером называется «счастливым», если сумма первых трёх цифр совпадает с суммой трёх последних. Посчитайте количество счастливых билетов.

Решите эту задачу в одну строчку

Если бы мы считали четырёхзначные билеты, то ответ был бы таким:

670

Не забудьте, что 000000 — тоже счастливый билет!

IDE

ZD: Развернуть элементы с чётными индексами

Дан список чисел. Переставьте его элементы следующим образом. Элементы с чётными индексами (0, 2, 4, ...) остаются на своих местах, а элементы с нечётными индексами меняют свой порядок на противоположный.

Выведите полученный список после модификации.

Решите эту задачу в три строчки. Первая строка — считывание списка, вторая строка — модификация списка, третья строка — вывод результата.

9 8 7 6 5 4 3 2
9 2 7 4 5 6 3 8
9 8 7 6 5 4 3 2 1
9 2 7 4 5 6 3 8 1
IDE

ZE: Переставить половинки списка

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

Выведите полученный список после модификации.

Решите эту задачу в три строчки. Первая строка — считывание списка, вторая строка — модификация списка, третья строка — вывод результата.

9 8 7 6 5 4 3 2
5 4 3 2 9 8 7 6
9 8 7 6 5 4 3 2 1
4 3 2 1 5 9 8 7 6
IDE