Символы, которые встретились больше одного раза
Дана строка s.
Напишите функцию duplicate_chars(s), которая вернет список символов, встречающихся в строке больше одного раза.
Символы в ответе должны идти в порядке первого появления в строке. Регистр учитывается: "A" и "a" считаются разными символами.
Решение прямо на странице
Напишите код, запустите проверки и только потом открывайте разбор.
Нажмите «Запустить проверки» или Ctrl+Enter.
Показать разбор
Идея решения
Сначала считаем частоты символов, затем еще раз идем по строке и добавляем символ в ответ при первом появлении, если его частота больше одного. Множество added нужно, чтобы не положить один и тот же символ несколько раз.
Эталонный код
from collections import Counter
def duplicate_chars(s):
counts = Counter(s)
answer = []
added = set()
for ch in s:
if counts[ch] > 1 and ch not in added:
answer.append(ch)
added.add(ch)
return answer
LTV/R365 и годовой data drift
Нужно прогнозировать выручку пользователя за 365 дней по ранним признакам. Почему прямой подход может плохо работать?
Сначала проговорите ответ вслух или тезисами.
Формулы, план решения, риски и примеры.
Откройте разбор только после своей попытки.
Показать разбор
Короткий ответ
Для R365 нужны когорты, прожившие год, а значит train будет старым. За год продукт, маркетинг и поведение игроков меняются, поэтому появляется сильный train-test drift.
Подробный разбор
Прямой прогноз R365 выглядит просто: взять признаки первых дней пользователя и обучить регрессию на накопленную выручку за 365 дней. Проблема в задержке target. Для полного label нужны пользователи, пришедшие минимум год назад. Если продукт быстро меняется, train-когорты уже не похожи на текущих пользователей.
Drift может прийти из новых источников трафика, изменения монетизации, баланса игры, промо, регионов, платежных механик и сезонности. Модель может хорошо работать на старом holdout и плохо ранжировать новые когорты.
Поэтому важно валидироваться по времени, смотреть качество на последних доступных когортах, мониторить calibration и не доверять случайному split по пользователям.
Типичные ошибки
- Делать random split вместо time split.
- Не учитывать изменения acquisition channel.
- Оценивать только RMSE без бизнес-срезов по когортам.
Multi-output прогноз LTV-кривой
Как использовать свежие неполные когорты, если R365 для них еще неизвестен?
Сначала проговорите ответ вслух или тезисами.
Формулы, план решения, риски и примеры.
Откройте разбор только после своей попытки.
Показать разбор
Короткий ответ
Предсказывать не только R365, а вектор горизонтов: R7, R14, R30, R60, R180, R365. Тогда свежие когорты дают labels на короткие горизонты, а старые - на длинные.
Подробный разбор
Вместо одной головы R365 можно учить модель прогнозировать LTV-кривую или набор накопленных горизонтов. Для старых когорт известны все горизонты, для свежих - только короткие. Это позволяет учить ранние головы на актуальных данных и связывать их с поздними горизонтом через shared representation.
Есть несколько вариантов: multi-output regression, survival/hazard modeling, curve fitting, прогноз инкрементов по периодам или модель отношения R365/R30. Важно не дать модели увидеть будущую информацию: признаки должны быть доступны на момент принятия решения.
Валидация делается по времени и по бизнес-use case. Если модель нужна для user acquisition, важна способность рано ранжировать кампании и пользователей, а не только точный абсолютный R365.
Типичные ошибки
- Обучать R365 только на старых когортах и не использовать свежие короткие targets.
- Смешивать накопленные и инкрементальные targets без ясного контракта.
- Не проверять calibration на последних когортах.