PythonTalk
5.11K subscribers
1.61K photos
50 videos
6 files
1.39K links
Привет, меня зовут Олег Булыгин 👋

🐍 Здесь я делюсь полезной информацией для тех, кто пишет код на Python: от разработки до Data Science.

По вопросам: @obulygin91
Download Telegram
Задачка про анаграммы в строке 🐍

👨‍💻 У нас есть две строки, s1 и s2. Нужно написать функцию, которая определит, содержит ли строка s2 в себе любую из перестановок строки s1 в качестве непрерывной подстроки.

Проще говоря, является ли какая-либо анаграмма s1 подстрокой в s2.

Для ясности, пара примеров 👇🏻
# Пример 1
s1 = "abc"
s2 = "lecabee"
# Вывод: True, потому что в s2 есть подстрока "cab",
# а это перестановка "abc".

# Пример 2
s1 = "abc"
s2 = "lecaabee"
# Вывод: False, потому что ни "abc", ни "acb", ни "bac" и т.д.
# не встречаются в s2 как единая подстрока.

Простое решение "в лоб" тут, конечно, есть, но оно не впечатлит 🌝 Хочется увидеть что-то изящное и эффективное.

Как решать будем? 🧠

#алгособес
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥22👌1
This media is not supported in your browser
VIEW IN TELEGRAM
Надоело смотреть на стандартные графики функции потерь?

🏂 Встречайте, LossRider — библиотека для построения графиков с seaborn-подобным интерфейсом, которая на выходе генерирует не жалкий .png, а трек для... Line Rider.

Да, той самой флеш-игры из нулевых, где человечек на санках едет по нарисованной вами линии.

Автор даже приложил примеры с данными из реальной ML-статьи про u-µP.

Есть поддержка нескольких линий (hue — для каждого свой наездник!), логарифмических шкал и кастомизации осей.

#фана_ради
🔥10👍221
🤥 Врут и не краснеют

По данным свежего исследования от hh.ru, 54% работодателей сталкивались с откровенной липой в резюме кандидатов. Почти каждый второй!

И речь не просто приукрашивание. Речь о фиктивных проектах, выдуманных должностях и накрученном опыте. Иллюзия экспертизы вместо реальных скиллов.

Кто у нас в лидерах этого маскарада?
🥇 Разработчики (20%)
🥈 Тестировщики и руководители проектов (по 15%)
🥉 Менеджеры продуктов (12%)

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

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

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

И что в итоге?
Для 43% работодателей такая ложь — это мгновенный отказ. Не из-за некомпетентности, а из-за вранья.

Надеюсь, в таком цирке надолго не застрянем 😩

#денюжки
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11😢3👀2🙈211
🐍 Разбор задачи: анаграмма в строке

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

Давайте посмотрим на два основных подхода 👇


🐢 Решение "в лоб"

Был предложен самый прямолинейный подход: сгенерировать все возможные перестановки (анаграммы) строки s1 и проверить, есть ли хоть одна из них в строке s2.

Вот как это выглядит:

from itertools import permutations

def check_inclusion_bruteforce(s1: str, s2: str) -> bool:
all_permutations = permutations(s1)
for p in all_permutations:
if "".join(p) in s2:
return True
return False


Как это работает?
Просто, как валенок: берём s1 = "abc", получаем "abc", "acb", "bac", "bca", "cab", "cba" и по очереди ищем каждую из них в s2.

В чём проблема?
В производительности! Сложность генерации всех перестановок — O(k!), где k — длина s1. Для строки из 10 символов это уже 3,628,800 операций, а для 13 — больше 6 миллиардов 😬


🚀 Скользящее окно

А теперь — элегантный и максимально эффективный способ. Вместо перебора всех анаграмм, мы будем проверять "отпечатки" подстрок в s2. Для этого идеально подходит техника скользящего окна и счётчики (collections.Counter).

Это лучшее решение по сочетанию эффективности и идиоматичности Python.

from collections import Counter

def check_inclusion_optimal(s1: str, s2: str) -> bool:
len1, len2 = len(s1), len(s2)
if len1 > len2:
return False

s1_counter = Counter(s1)
window_counter = Counter()

for i in range(len2):
# Добавляем правый символ в окно
window_counter[s2[i]] += 1

# Если окно стало слишком большим, убираем левый символ
if i >= len1:
left_char = s2[i - len1]
if window_counter[left_char] == 1:
del window_counter[left_char]
else:
window_counter[left_char] -= 1

# Сравниваем счётчики, как только окно достигло нужного размера
if window_counter == s1_counter:
return True

return False


Как это работает?
1️⃣ Создаём "эталонный" счётчик символов для строки s1. Например, для "abc" это будет {'a': 1, 'b': 1, 'c': 1}.
2️⃣ Запускаем "окно" размером с s1 по строке s2.
3️⃣ На каждом шаге сдвигаем окно на один символ вправо: добавляем новый символ в наш счётчик окна и убираем самый левый (старый).
4️⃣ После каждого сдвига сравниваем счётчик символов в окне с "эталонным" счётчиком s1. Если они совпали — ура, мы нашли анаграмму! 🎉

Чего по сложности?
Время: O(N), где N — длина s2. Мы проходим по s2 всего один раз. Линейное время, быстрее некуда!
Память: O(1), так как размер счётчиков не превышает размер алфавита (например, 26 для английских букв).

#алгособес
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥103👍22
Помните, обсуждали инструменты для автоматизации составления резюме?

На нашем рынке, оказывается, тоже такое есть — вот ИИ-ассистент, который полностью автоматизирует процесс поиска работы:

⭐️ Она сама составляет резюме, на основании опыта работы и публикует его на хх.ру.

⭐️ Делает до 20 откликов в день.

⭐️ Пишет индивидуальное сопроводительное под каждую вакансию (можно выбрать стиль сообщения).

⭐️ Переписывается с рекрутером и отвечает на его вопросы. А еще помогает в подготовке к собесам - внутри приложения есть отдельный тренажер, где можно пройти тестовый собес к любой вакансии.

Пользователи отмечают, что с Софи поиск работы занимает 10-15 минут в день, что очень разгружает время.

Ребята работают всего пару месяцев и открывают доступ партиями. Следующий доступ откроется 21 октября в 19:00 по мск, будет 3 дня бесплатного теста.

Анонс будет в этом канале ◀️

Интересно будет потестить 😏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍6🤔2🤯2👎1🙏1
Проверяем, насколько вы и ваш внутренний интерпретатор дружите с распаковкой.

#квиз
👍3🤔22
🔥7👍33
This media is not supported in your browser
VIEW IN TELEGRAM
👨‍💻 IDE расслабили наши пальцы

ИИ-шные автодополнения научили нас очень быстро tabать 🌝

Но стоит зайти по ssh на сервер, в docker exec или просто открыть vim/nano, то там уже помощников нет (или я про них не знаю?). Остаешься один на один со своей скоростью печати.

Наткнулся на прикольный консольный тренажер слепой печати для программистов — ttyper.

Чем он лучше сотен других?

🎯 Тренировка на коде. Самое главное. Вместо унылых "The quick brown fox..." можно тренироваться на ключевых словах из Python и других языков. Наконец-то можно оттачивать def __init__(self): и import pandas as pd, а не рандомные тексты.

🦀 Написан на Rust. Для нас это сигнал качества. Работает молниеносно, не падает, не жрет ресурсы. Мелочь, а приятно.

🔧 Глубокая кастомизация. Можно создавать свои собственные "языки" для тренировки. Просто кидаете текстовый файл со списком слов — и вперед.

Скормите ему список всех переменных и функций из вашего рабочего проекта. Слабо без ошибок напечатать calculate_annual_recurring_revenue_with_churn_projection с первого раза? 😉

Забирайте и тренируйтесь: https://github.com/max-niederman/ttyper

Кстати, а какая у вас скорость печати? Признавайтесь в комментах, замеряли когда-нибудь? 👇

#тулбокс
👍5🔥432❤‍🔥1
👨‍💻 Мистер Мисикс на Python: эталонный пет-проект

Подписчик @nkerios написал, что ему пришла в голову идея сделать мистера Мисикса из "Рика и Морти" — чтобы он появлялся, отвечал на вопрос через локальную LLM и... исчезал. Прям как в мультике.

И ведь сделал же! Ссылка на GitHub, если хотите сразу заценить: Meeseeks Box .

Получился отличный шаблон для создания своих десктопных AI-утилиток на Python.

Что под капотом:
- Легковесная связка Flask + Pywebview.
- Приложение само находит активную модель в LM Studio. Не надо ничего ковырять руками.
- Чистая и управляемая покадровая SVG-анимация.

Разобрал всю техническую начинку по косточкам: Meeseeks Box: Как превратить Python-скрипт в десктопное приложение ◀️

Будьте как @nkerios👍

#щупаем_сорцы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥41🙏1🆒1
Парочка тезисов о вранье/преувеличении в резюме

Проблема вранья в резюме — это классический конфликт между личной выгодой и коллективным проигрышем.
В вакууме, для одного конкретного человека, стратегия "приукрасить" может сработать. Если ты хакнул неэффективную систему найма, получил оффер, а потом реально тащишь на работе — кто в проигрыше? Вроде бы никто. Можно считать это просто инструментом для прохождения фильтров. Fake it till you make it.

Fake it till you make, но только если в итоге you make it, иначе будет больно.


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

🔄 Происходит такая петля:

1️⃣ Отдельные спецы, отчаявшись, раздувают резюме выдумками.

👇

2️⃣ Работодатели и HR, видя поток "сильных" резюме, принимают это за новую норму, новый baseline.

👇

3️⃣ Честные кандидаты, чтобы хоть как-то конкурировать, тоже вынуждены начинать "соответствовать" — то есть врать.

👇

4️⃣Требования в вакансиях растут до абсурда, а этапы отбора превращаются в допрос с пристрастием, чтобы отсеять лжецов. Возвращаемся к пункту 1, только на новом, более упоротом уровне.

В итоге мы получаем гонку вооружений: кандидаты соревнуются, кто круче нафантазирует, а компании — кто изощрённее придумает фильтры. Страдают все: и честные спецы, которые не проходят по формальным (раздутым) требованиям, и сами компании, которые тратят кучу ресурсов на просев тонн шлака.

☝🏻 В игре, где обман даёт преимущество, читер выигрывает, только пока остальные играют честно. Когда врать начинают все — проигрывают все.

На эту тему есть отличная интерактивная демонстрация по теории игр — The Evolution of Trust. Наглядно показывает, как в системах, основанных на взаимодействии, доверие становится самым ценным ресурсом, а обман ведет к коллапсу.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥631❤‍🔥1👌1💯1
Помните, пару недель назад мы с вами выбирали название для закрытого комьюнити? Большинство проголосовало за «Точку Сборки». Что ж, я почти закончил сборку. Скоро запускаемся.

И да, он будет платный. 👉

Что это за движуха и зачем она нужна?
Помимо закрытого чатика, где можно будет обсуждать всякое с вовлечёнными людьми, я планирую организовывать по две онлайн-встречи в месяц . Иногда буду проводить сам (в рамках своей экспертизы в Python и DS), иногда — притаскивать толковых людей, которым я доверяю, и которым не страшно доверить ваше время.

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

С чего начнем?
Первая тема: "Обзор чат-ботов, которые я использую в задачах программирования (и не только)". Преимущественно подойдёт для начинающих, которые еще не обмазались агентами, AI-based IDE и просто хотят больше использовать нейронки для своих небольших задач и/или учебных проектов. Будет сравнение, мои рекомендации.

Надо ли это кому-то, кроме меня?
Прежде чем всё это начитать, я хочу понять, есть ли на это спрос. Поэтому, пожалуйста, ткните в опрос ниже. Это даст мне понять, стоит ли вообще продолжать работу над этим долгосрочным проектом. Если опрос покажет, что движуха интересна, то в течение недели-двух я открою продажи.
Для первых 20 человек будут вкусные условия 🥰
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍3🎉21🆒1
Гвидо ван Россум дал новое интервью 🐍

Создатель Python высказался про AI, GIL, Mojo и будущее языка. Выбрал для вас самую мякотку:

1️⃣ AI – это перегретый хайп, а будущее с ним – пугает.
Гвидо не разделяет всеобщего восторга. Более того, он прямо говорит об опасностях. Никаких тебе "AI изменит мир к лучшему".

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


На вопрос, что бы он добавил в ядро Python для нужд современного AI, ответ был такой:
Ничего не приходит на ум. AI переоценен. Это по-прежнему просто софт.


2️⃣ Отмена GIL – хайп для корпораций, а не для всех.
Пока все радуются no-GIL Python, Гвидо смотрит на это с большим скепсисом. Он считает, что это усложнит жизнь контрибьюторам и нужно в первую очередь бигтехам.

Честно говоря, я думаю, что важность проекта по удалению GIL была сильно преувеличена. Он служит нуждам крупнейших пользователей (например, Meta), усложняя жизнь потенциальным контрибьюторам в кодовую базу CPython... Я беспокоюсь, что Python становится слишком корпоративным, потому что крупные корпоративные пользователи могут платить за новые функции, которые нужны только им.


3️⃣ Типизация нужна не всем и не всегда.
Гвидо, который был одним из главных сторонников type hints, очерчивает четкую границу их применения.

Я бы сказал, что граница для использования тайп-хинтов — это около 10 000 строк кода. Ниже этого порога ценность снижается... Но как только вы достигаете 10 000, поддерживать качество кода без тайп-хинтов становится трудно. Впрочем, я бы не навязывал их новичкам в языке.


4️⃣ Новые языки типа Mojo – не конкуренты.
Про угрозу со стороны "убийц Python" Гвидо высказывается предельно ясно. У них своя ниша, и они не заменят экосистему.

Mojo предназначен для реализации высокопроизводительных "ядер" AI... У него нет шансов заменить экосистему Python — это просто не то, чем они интересуются.


5️⃣ Главное наследие Python – не технологии.
В конце Гвидо говорит о том, что для него действительно важно. И это не про деньги или доминирование на рынке.

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


Прагматик и гуманист 👍
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍21🔥10👏531🙏1
Проверять мы, конечно, это не будем.

Пошёл проверять 🚶‍♂️
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣21😁6🌚2🔥1🙏1
Зачем писать 8 строк кода, если можно обойтись двумя? 🧐

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

Вот классический подход:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y

def __repr__(self):
return f"Point(x={self.x}, y={self.y})"

def __eq__(self, other):
return self.x == other.x and self.y == other.y


8 строк бойлерплейта, чтобы просто хранить два числа.

А вот как надо:
from dataclasses import dataclass

@dataclass
class Point:
x: int
y: int


И это лишь один из 6 классических сценариев неуместного ООП, где мы пишем лишний код по инерции. Остальные пять — от утилитных "классов-папок" до самодельных конфигов — разобрал в статье, читайте ◀️◀️

#это_база
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍422🔥1
🧠 Группируем анаграммы

Вот вам классика с собесов, на которой до сих пор многие сыпятся.

Суть такая: дан список строк. Ваша задача — сгруппировать из них анаграммы.

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

На входе:
strs = ["eat", "tea", "tan", "ate", "nat", "bat"]

На выходе должно быть что-то такое:
[["bat"], ["nat", "tan"], ["ate", "eat", "tea"]]

Или вот ещё пример:
На входе:
strs = ["act", "pots", "tops", "cat", "stop", "hat"]

На выходе:
[["hat"], ["act", "cat"],["stop", "pots", "tops"]]

Как бы решали?

#алгособес
2🔥21👏1🙏11
Спасибо всем, кто поучаствовал в опросе о закрытом канале ❤️

Особый респект 20%, которые пришли в интернет за деградацией — уважаю ваш выбор 😁

Теперь к делу. Что по ценам?

Будет два тарифа:
1 месяц за 1490 ₽
3 месяца за 3990 ₽

НО.

Как и обещал, для самых первых будет спецусловие. Для тех, кто готов вписаться в эту движуху с самого начала будет тариф на 3 месяца всего за 2990 ₽.
При этом условия будут сохраняться при продлении тарифа (если я не нафакапил с настройками платежей, не так часто это делаю 😅 но это поправимо). Таких мест 20.

🗓 В пятницу будет пост со ссылкой на бота для подписки.

🚀 А наш первый эфир по чат-ботам состоится предварительно вечером 7 ноября.

Пишите, готовы ли участвовать и ваши вопросы, если сомневаетесь 👇
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍42🆒111
🐍 Разбор задачки по группировке анаграмм

🏆 В решении-чемпионе по эффективности используется подсчет символов вместо сортировки.

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

from collections import defaultdict

def group_anagrams_count(strs):
groups = defaultdict(list)
for word in strs:
count = [0] * 26
for char in word:
count[ord(char) - ord('a')] += 1

groups[tuple(count)].append(word)

return list(groups.values())


Как это работает? 🤔

1. Мы создаем словарь groups, где ключом будет кортеж (tuple) с количеством букв, а значением — список самих слов-анаграмм.
2. Для каждого слова word мы создаем массив count из 26 нулей — по одному на каждую букву английского алфавита.
3. Пробегаемся по буквам char в слове и увеличиваем счетчик для соответствующей буквы. Например, для 'c' увеличится count[2].
4. В итоге для слов "eat" и "tea" массив count будет одинаковым. Мы превращаем его в кортеж tuple(count), потому что списки не могут быть ключами словаря, и используем как ключ.
5. Добавляем исходное слово в список по этому ключу.

Асимптотика:
- Время: O(N * K), где N — количество слов, а K — максимальная длина слова. Это быстрее, чем сортировка!
- Память: O(N * K) для хранения результата.


Альтернативный и хороший способ, наверное, более "питоничный", но не такой эффективный.

from collections import defaultdict

def group_anagrams_sorted(strs):
anagrams = defaultdict(list)
for s in strs:
sorted_str = "".join(sorted(s))
anagrams[sorted_str].append(s)
return list(anagrams.values())


Как это работает? 💡

1. Главная идея: у всех анаграмм отсортированная версия будет одинаковой. sorted("eat") -> ['a', 'e', 't'], и sorted("tea") -> ['a', 'e', 't'].
2. Мы берем каждое слово s, сортируем его буквы и склеиваем обратно в строку ''.join(...).
3. Эта отсортированная строка становится идеальным ключом в нашем словаре anagrams.
4. Все слова, у которых отсортированная версия совпадает, попадают в один список.

Асимптотика:
- Время: O(N * K log K). Основное время здесь уходит на сортировку каждого слова (K log K), и мы делаем это N раз.
- Память: O(N * K) для хранения словаря.

#алгособес
👍7🔥3👏2🙏2👌2
Декораторы знаете? 😏

#квиз
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🙏2👌1