Don Python [DATA SCIENCE]
71 subscribers
6 photos
1 file
19 links
Путь python разработчика после 30. Знания, обсуждения, книги, rock & roll
Download Telegram
🔄 Числа Фибоначчи

У skillbox есть отличная статья на эту тему, но я приведу только определение:

Числа Фибоначчиэто последовательность чисел, которые задаются по определённому правилу. Оно звучит так: каждое следующее число равно сумме двух предыдущих. Первые два числа заданы сразу и равны 0 и 1.


Последовательность Фибоначчи задаётся линейным рекуррентным соотношением, которое можно выразить формулой:

F0 = 0, F1 = 1, Fn = Fn-1 + Fn-2

Можно записать эту формулу в виде функции:

def fibonacci(n):
if n == 0:
return 0
elif n == 1 or n == -1:
return 1
elif n < 0:
return int((-1)**(n+1) * fibonacci(-n))
else:
return fibonacci(n - 1) + fibonacci(n - 2)

print(f'Result: {fibonacci(4)}')


Функция простая и может стать отправной точкой для изучения возможностей рекурсии в программировании.

Good coding 👨🏻‍💻

#recursion #fibonacci
❤‍🔥1
📕 Последовательности символов в строке

Я решаю задачки на сайте DMOJ и одна задача поставила меня в небольшой тупик.
Главная трудность заключалась в написании небольшой функции, которая принимала строку без пробелов, а возвращала бы строку, где каждая непрерывная последовательность одинаковых символов была бы представлена в следующем виде: 3 p, где цифра 3 обозначает сколько символов p было в последовательности. Сейчас будет понятней:

Строка входа

input = 'pppqqq++++'


Строка выхода

output = '3 p 3 q 4 +'


В итоге как с помощью python из строки input получить строку output?

Решение кроется в 14 строках:

def compress_string(string):
compressed = []
count = 1

for i in range(1, len(string)):
if string[i] == string[i - 1]:
count += 1
else:
compressed.append(f"{count}({string[i - 1]})")
count = 1
compressed.append(f"{count}({string[-1]})")
return " ".join(compressed)

print(compress_string('pppqqq++++'))


Good coding 🧑‍💻

#problem #string #algorithm
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🤷‍♂️ Копирование списка

У нас есть простой список: x = [1, 2, 3, 4, 5, 6, 7]


Мы без проблем можем изменить любой элемент списка по индексу:

x[0] = 99  # x == [99, 2, 3, 4, 5, 6, 7]


Рассмотрим следующий код:

x = [1, 2, 3, 4, 5, 6, 7]

y = x

x[0] = 99

print(y) # y == [99, 2, 3, 4, 5, 6, 7]


Следуя обычной логике, можно предположить что 'y' должен содержать в себе изначальное состояние списка 'x'. Но в python, если мы напрямую присваиваем переменной список без дополнительных манипуляций, то эта переменная не получает копию списка, она получает ссылку на присваиваемый список.

Что бы копировать список, можно в момент присваиваний сделать срез для списка 'x', вот так: y = x[:]. Тогда 'y' получит копию списка 'x', а не ссылку на него.

Good coding 🧑‍💻

#list #python #5min_py
Please open Telegram to view this post
VIEW IN TELEGRAM
11
🌡 List comprehension

Или генератор списка на русском.

В одной задаче нужно было создавать и наполнять список получив предварительно каждое значение из пользовательского ввода ( input ). Моё решение выглядело так:

villages_count = int(input())

villages = []
for _ in range(villages_count):
village = int(input())
villages.append(village)


Но пять строк магическим образом могут превратиться в две:

villages_count = int(input())
villages = [int(input()) for _ in range(villages_count)]


Подробнее о теме можно почитать тут — Руководство по использованию list comprehension

Good coding 🧑‍💻

#list #python #5min_py
Please open Telegram to view this post
VIEW IN TELEGRAM
11
[PROBLEM] Basketball game

Иногда решить задачу легче, чем ее описать.

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

Сложность для junior: 7 / 10

Задача с решением на русском здесь

———

Good coding 🧑‍💻

#python #problem #list
Please open Telegram to view this post
VIEW IN TELEGRAM
11
⬆️ [INFO] Надо добавить элемент в произвольную позицию списка

🚩 Вариант

Метод insert(). Работает он просто: первым параметром передаём индекс, по которому будет находится новый элемент, а вторым параметром передаём сам элемент.

my_list = [1, 2, 3, 5]
my_list.insert(3, 4)
print(my_list)

# output [1, 2, 3, 4, 5]


Если следовать простой логике, то можно подумать, что число 4 должно заменить число 5. Но на самом деле, если по указанному индексу находится элемент, то индекс этого элемента и всех элементов после него увеличивается на 1. В наше случае индекс числа 5 становится 4, а третий индекс занимает число 4.

🚩 Вариант

Мы можем добавить элемент с помощью среза.

my_list = [1, 2, 3, 5]
my_list[3:3] = [4]
print(my_list)

# output [1, 2, 3, 4, 5]


Что бы это работало, нужно соблюсти два условия:

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

Операции со срезами могут изменять последовательность в списке, но только при условии, что мы присваиваем другой итерируемый объект, такой как список. Срез возвращает не один элемент, а последовательность элементов (список), и, соответственно, при присвоении Python ожидает последовательность в качестве значения.


Первый вариант более академичный, второй лаконичный, но любой из них правильный.

———

Good coding 🧑‍💻

#python #5min_py #list
Please open Telegram to view this post
VIEW IN TELEGRAM
11
[PROBLEM] Mountain streams

Многие реки берут своё начало в горах, когда множество маленьких ручьев объединяются в один бурный поток. В этой задаче нам предстоит смоделировать природное явление на уровне кода.

Сложность для junior: 5 / 10

Задача с решением на русском здесь

* Прежде чем смотреть готовое решение,желательно потратить 2-3 часа на самостоятельные попытки. И если не получится, то переходить к анализу ответа.

———

Good coding 🧑‍💻

#python #problem #list
Please open Telegram to view this post
VIEW IN TELEGRAM
11
⬆️ [INFO] Функция map()

В процессе разработки вы в любом случае столкнетесь с ситуацией, когда с каждым элементом итерируемого объекта нужно будет совершить одно и то же действие.

Предположим что в ходе работы разработчик получает список чисел — numbers = [5, 5, 10, 25, 35, 70]
Что бы работать дальше с этим списком, необходимо преобразовать его в строку. Если попробовать преобразовать напрямую, то код 'упадет' с ошибкой:

numbers = [5, 5, 10, 25, 35, 70]
str_numbers = ' '.join(numbers)

# >>> TypeError: sequence item 0: expected str instance, int found


Очевидный способ решения — это пробежаться циклом for по всем элементам списка:

numbers = [5, 5, 10, 25, 35, 70]
str_streams = [str(number) for number in numbers]
string = ' '.join(str_streams)

print(string)

# >>> 5 5 10 25 35 70


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

Так как здесь затрагивается часть идеи функционального программирования, советую почитать об этом стиле на странице официального источника


Посмотрим на преобразованный код:

numbers = [5, 5, 10, 25, 35, 70]
string = ' '.join(map(str, numbers))

print(string)

# >>> 5 5 10 25 35 70


Выглядит не плохо, мы избавились от одной строки, но код стал даже более очевидным. Что в нашем случае делает map()? Буквально принимает два аргумента: функцию и итерируемый объект.

Функция
map()
применяет переданную в параметрах функцию к каждому элементу переданного в параметрах итерируемого объекта, после чего возвращает преобразованный итерируемый объект


Для этого короткого примера не потребуется развернутого объяснения. По сути, если словами выразить команду map(str, numbers), то получится: преобразуй в строку каждое число в списке numbers с помощью функции str.

[WARN] Функция передаваемая в параметрах должна передаваться без вызова, то есть без скобок. Если мы передадим и сразу вызовем функцию, то произойдет ошибка:

numbers = [5, 5, 10, 25, 35, 70]
string = ' '.join(map(str(), numbers))

print(string)

# >>> TypeError: 'str' object is not callable


Функция map позволяет делать больше, чем можно описать в посте. Предлагаю особо любопытствующим почитать long read на тему.

———

Good coding 🧑‍💻

#python #function #5min_py #map
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🤕 [SHORT] Не очевидное создание кортежа

При создании кортежа можно опустить скобки. Нужно ли? Дело каждого, но язык позволяет это сделать:

numbers = 5, 5, 10, 25, 35, 70
print(numbers)

# >>> (5, 5, 10, 25, 35, 70)


———

Good coding 🧑‍💻

#python #tuple #short
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🤕 [SHORT] Оператор else для цикла

В Python блок else может использоваться не только в условных конструкциях if, но и с циклами for и while. Блок else в цикле выполняется, если цикл завершился "нормально", то есть без прерывания с помощью оператора break. Если же цикл был прерван с помощью break, блок else не выполнится. Это позволяет, например, выполнить определенный код в конце цикла, если цикл не был прерван.

for i in range(5):
if i == 3:
print("Цикл прерван на итерации:", i)
break
else:
print("Цикл завершился без прерываний")


В этом цикле блок кода после else не выполнится. Но следующий цикл "переживет" все итерации и блок else выполнится:

for i in range(5):
print("Текущая итерация:", i)
else:
print("Цикл завершился без прерываний")


———

Good coding 🧑‍💻

#python #else #for #while #short
Please open Telegram to view this post
VIEW IN TELEGRAM
2
[PROBLEM] Asya the cat is playing with boxes

Перевод и решение задачи посвящается прекрасной кошке Асе. На самом деле с коробками любит играть кот Арсений. Поэтому у Аси не нашлось фото с коробкой 🐈🐈

Сложность для junior: 4 / 10

Задача с решением на русском здесь

* Прежде чем смотреть готовое решение,желательно потратить 2-3 часа на самостоятельные попытки. И если не получится, то переходить к анализу ответа.

———

Good coding 🧑‍💻

#python #problem #list
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🤕 [SHORT] Памятка по созданию и подключению виртуального окружения

Открываем терминал в корне проекта и прописываем — python -m venv venv

— Флаг -m используется для запуска venv как исполняемого модуля.

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

💻 Создание окружения в pycharm без терминала

— Проходим по пути settings - project:<your_project> - python Interpreter для открытия окна с настройками виртуального окружения

— Нажимаем справа сверху add Interpreter и выбираем add local Interpreter

— Настройте интерпретатор и нажмите OK. По сути в Base Interpreter просто выберите доступный интерпретатор и это все настройки

🖥 Активация

Что бы активировать окружение на windows введите .\venv\Scripts\activate, где venv название директории с виртуальным окружением.

Для активации на mac и linux введите source venv/bin/activate

Если вы используете git bash, то команда активации будет следующей — source venv/Scripts/activate


Что бы отключить окружение введите deactivate

———

Good coding 🧑‍💻

#python #memo #venv
Please open Telegram to view this post
VIEW IN TELEGRAM
2
[PROBLEM] Big wash

Задача о том, как программисты добывают себе одежду 🛒

Сложность для junior: 7 / 10

Задача с решением на русском здесь

* Прежде чем смотреть готовое решение,желательно потратить 2-3 часа на самостоятельные попытки. И если не получится, то переходить к анализу ответа.

———

Good coding 🧑‍💻

#python #problem #list
Please open Telegram to view this post
VIEW IN TELEGRAM
3
😴 [OFFTOP] Мега крестики-нолики

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

Играя в карты можно быть уверенным, что каждая партия уникальна и никогда не повториться. А общее количество уникальных партий в крестики нолики, учитывающих победы и ничьи, составляет 26 830.

Довольно скромно 😐

Недавно я прочитал книгу. Называется 'Математика с дурацкими рисунками'. Оттуда и узнал про интересную модификацию крестиков-ноликов.

Суть в том, что поле игры всё так же состоит из 9 квадратов, но теперь каждый квадрат является самостоятельным полем крестиков-ноликов размером 3x3. В итоге поле представляет собой 9 отдельных "классических" игр в крестики-нолики.

Как программисты мы можем представить такое поле в виде трехмерной матрицы:

game_board = [
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']],
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']],
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']],
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']],
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']],
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']],
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']],
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']],
[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']]
]

Весь game play строится на том, что поле, в котором игрок будет делать ход, зависит от хода его соперника. Например: если первый игрок поставил X в центральную клетку одного из малых полей, то следующий игрок должен поставить свой O на центральное большуо поле.

Подробные правила читайте тут — тык

☺️ Так вот..

В классическом варианте игры, при должном терпении, мы могли бы сыграть 26 830 возможных уникальных партий и сказать, что мы видели всё и нам скучно. Но в мега варианте такой роскоши себе позволить нельзя. Здесь мы получаем приморно 10^30 уникальных партий. Это вот такое число 1000000000000000000000000000000, которое называется нониллион. Даже если прожить 100 лет и каждую секунду играть уникальную партию, нам не удастся перебрать даже 1% возможных вариантов.

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

Игру можно посмотреть в репазитории.
Если кому то будет интересно, можно дописать к ней интерфейс. Сейчас весь game play осуществляется только через консоль.

Буду рад комментариям, оценкам, критике и исправлениям.

Также ссылка на вдохновившую меня книгу — Математика с дурацкими рисунками

———

Good coding 🧑‍💻

#python #list #matrix #game #offtop
Please open Telegram to view this post
VIEW IN TELEGRAM
21
[PROBLEM] Tides

Представьте что вы попали на необитаемый остров. Чем бы занялись? Можно добыть еды или обустроить жилище, а можно как наш герой наблюдать за приливами и отливами 🐳

Сложность для junior: 5 / 10

Задача с решением на русском здесь

* Прежде чем смотреть готовое решение,желательно потратить 2-3 часа на самостоятельные попытки. И если не получится, то переходить к анализу ответа.

———

Good coding 🧑‍💻

#python #problem #list
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🤕 [SHORT] Циклический сдвиг списка

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

С созданием копии списка:

my_list = [1, 5, 2, 4, 3]
new_list = my_list[:]

for i in range(len(my_list)):
my_list = new_list[i:] + new_list[:i]


Без копии:

my_list = [1, 5, 2, 4, 3]

for _ in range(len(my_list)):
my_list.append(my_list[0])
my_list.pop(0)


Выбор способа зависит от задачи.

———

Good coding 🧑‍💻

#python #short #list
Please open Telegram to view this post
VIEW IN TELEGRAM
3
⬆️ [INFO] Поиск пересечений

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

a = [5, 4, 1, 3, 2]
b = [1, 3, 2, 5, 4]


Соедините мысленно все одинаковые числа линиями. Как с помощью python посчитать количество пересечений?

Рассмотрим функцию find_intersections

def find_intersections(left_side, right_side):
num_fields = len(left_side)
intersections = 0

right_indices = {right_side[i]: i for i in range(num_fields)}

for i in range(num_fields):
for j in range(i + 1, num_fields):
left_cow_a = left_side[i]
left_cow_b = left_side[j]

right_cow_a = right_indices[left_cow_a]
right_cow_b = right_indices[left_cow_b]

if right_cow_a > right_cow_b:
intersections += 1

return intersections


Функция find_intersections подсчитывает количество "пересечений" между элементами двух списков — left_side и right_side.

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


1. Инициализация переменных:

num_fields — количество элементов в списках (они одинаковой длины).

intersections — счетчик пересечений, инициализируется нулем.

2. Создание словаря индексов:

right_indices — это словарь, где каждому элементу из списка right_side сопоставляется его индекс. Это нужно, чтобы быстро находить позиции элементов из right_side.

3. Два вложенных цикла для перебора пар элементов:


• Внешний цикл (for i in range(num_fields)) перебирает каждый элемент списка left_side как первый элемент пары.

• Внутренний цикл (for j in range(i + 1, num_fields)) перебирает каждый следующий элемент списка как второй элемент пары.

4. Сравнение порядков элементов в списках:

• Для текущей пары элементов left_cow_a (из left_side[i]) и left_cow_b (из left_side[j]), находятся их индексы в right_side с помощью словаря right_indices: это right_cow_a и right_cow_b.

• Если в right_side первый элемент пары (right_cow_a) находится позже второго (right_cow_b), то это пересечение, и счетчик intersections увеличивается на 1.

5. Результат:

• Функция возвращает общее количество пересечений.

Пример: Если:

left_side = [1, 2, 3]

right_side = [2, 1, 3]

• То пересечение будет между 1 и 2, так как их порядок в right_side обратен порядку в left_side.

———

Good coding 🧑‍💻

#python #info #list #matrix #algorithm
Please open Telegram to view this post
VIEW IN TELEGRAM
👍211
🤕 [SHORT] Поиск в множествах

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

Давайте убедимся на деле:

import time, random

# Генерируем список с дубликатами и преобразуем в множество
numbers_list = [random.randint(0, 10**6) for _ in range(10**6)]
numbers_set = set(numbers_list)

# Список случайных элементов для поиска
search_items = random.sample(range(10**6), 1000)

# Функция для замера времени поиска
def measure_search(container):
start = time.time()
for item in search_items:
item in container
return time.time() - start

# Замеры времени поиска
list_time = measure_search(numbers_list)
set_time = measure_search(numbers_set)

# Результаты
print(f"Поиск в списке: {list_time:.6f} сек") # Примерно 4.3 сек
print(f"Поиск в множестве: {set_time:.6f} сек") # Примерно 0.0009 сек


———

Good coding 🧑‍💻

#python #short #list #set
Please open Telegram to view this post
VIEW IN TELEGRAM
21
🤕 [SHORT] Инвертирование словаря

Предположим, что наше приложение — это что-то там связанное с английским. У нас есть некоторый словарь в котором ключ — это английское слово, а значение — перевод этого слова:

animals = {
'cat': 'кот',
'dog': 'собака',
'mouse': 'мышь',
'elephant': 'слон',
}


Нам нужно чтобы было наоборот: ключи на русском, а значения на английском. Пишем простое выражение:

print({value: key for key, value in animals.items()})

# >>> {'кот': 'cat', 'собака': 'dog', 'мышь': 'mouse', 'слон': 'elephant'}


———

Good coding 🧑‍💻

#python #short #dict
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🤕 [SHORT] Генерация алфавита. Функция chr()

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

alphabet = {chr(i): i - 64 for i in range(65, 91)}


Эта строчка генерирует словарь с прописными буквами английского алфавита.

Функция chr() конвертирует целое число в Unicode-символ и возвращает его.


Юникод и кодировки в Python

———

Good coding 🧑‍💻

#python #short #dict #unicode
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍11
🤕 [SHORT] Разворот списка, 3 способа

С помощью метода reverse()

my_position = ['first', 'second', 'third']
my_position.reverse()

print(my_position)
# >>> ['third', 'second', 'first']


С помощью функции reversed()

sequence = [1, 2, 3, 4, 5, 6]
reverse_sequence = list(reversed(sequence))

print(reverse_sequence)
# >>> [6, 5, 4, 3, 2, 1]


С помощью среза

split_name = ['r', 'd', 'n', 'a', 's', 'k', 'e', 'l', 'a']
reverse_split_name = split_name[::-1]

print(reverse_split_name)
# >>> ['a', 'l', 'e', 'k', 's', 'a', 'n', 'd', 'r']


———

Good coding 🧑‍💻

#python #short #list
Please open Telegram to view this post
VIEW IN TELEGRAM
21