diff --git a/results/top_tracks.txt b/results/top_tracks.txt index 60999b2..0278bc5 100644 --- a/results/top_tracks.txt +++ b/results/top_tracks.txt @@ -8,3 +8,388 @@ Rap God | Eminem | hip-hop | 950000 прослушиваний Wake Me Up | Avicii | electronic | 920000 прослушиваний Without Me | Eminem | hip-hop | 880000 прослушиваний Levels | Avicii | electronic | 870000 прослушиваний + +git clone https://git.vyatsu.ru/stud203985/MusicAnalyzer.git +cd ИМЯ_РЕПО +git config user.name "ТВОЕ ИМЯ" +git config user.email "ТВОЯ_ПОЧТА" +notepad solution.py +git add solution.py +git commit -m "Add skeleton" +git add solution.py +git commit -m "Implement solution" +git push +без глобал находясь в папке только в репе моем сейвинтсся + + +================ +def some_function(x): + return x + + +def main(): + print(some_function(...)) + print(some_function(...)) + + +if __name__ == "__main__": + main() +============================= + +# 1. is_armstrong(n: int) -> bool +# Проверяет, является ли число числом Армстронга. +# Идея: переводим число в строку, считаем количество цифр, +# затем суммируем каждую цифру в степени количества цифр. +def is_armstrong(n: int) -> bool: + digits = str(n) + power = len(digits) + total = 0 + + for ch in digits: + total += int(ch) ** power + + return total == n + + +# 2. intersection_of_sorted(a: list, b: list) -> list +# Находит пересечение двух отсортированных списков без дубликатов. +# Идея: используем два указателя i и j. +# Если элементы равны - добавляем в результат. +# Если элемент в первом списке меньше - двигаем i. +# Иначе двигаем j. +def intersection_of_sorted(a: list, b: list) -> list: + i = 0 + j = 0 + result = [] + + while i < len(a) and j < len(b): + if a[i] == b[j]: + if not result or result[-1] != a[i]: + result.append(a[i]) + i += 1 + j += 1 + elif a[i] < b[j]: + i += 1 + else: + j += 1 + + return result + + +# 3. longest_increasing_subsequence(arr: list) -> list +# Находит самую длинную возрастающую подпоследовательность. +# Идея: динамическое программирование. +# dp[i] хранит длину наибольшей возрастающей подпоследовательности, +# которая заканчивается в элементе arr[i]. +# prev[i] хранит индекс предыдущего элемента в этой подпоследовательности. +def longest_increasing_subsequence(arr: list) -> list: + if not arr: + return [] + + n = len(arr) + dp = [1] * n + prev = [-1] * n + + for i in range(n): + for j in range(i): + if arr[j] < arr[i] and dp[j] + 1 > dp[i]: + dp[i] = dp[j] + 1 + prev[i] = j + + max_index = 0 + for i in range(1, n): + if dp[i] > dp[max_index]: + max_index = i + + result = [] + while max_index != -1: + result.append(arr[max_index]) + max_index = prev[max_index] + + result.reverse() + return result + + +# 4. remove_duplicate_chars(s: str) -> str +# Удаляет из строки все повторяющиеся символы, +# оставляя только первое вхождение каждого символа. +# Идея: используем множество seen для хранения уже встреченных символов. +def remove_duplicate_chars(s: str) -> str: + seen = set() + result = "" + + for ch in s: + if ch not in seen: + seen.add(ch) + result += ch + + return result + + +# 5. most_frequent_value(d: dict) -> tuple +# Находит значение, которое чаще всего встречается среди значений словаря. +# Возвращает кортеж: (значение, частота). +# Идея: сначала считаем частоты значений в словаре counts, +# потом ищем значение с максимальной частотой. +def most_frequent_value(d: dict) -> tuple: + counts = {} + + for value in d.values(): + counts[value] = counts.get(value, 0) + 1 + + best_value = None + best_count = 0 + + for value, count in counts.items(): + if count > best_count: + best_value = value + best_count = count + + return best_value, best_count + + +# 6. gcd(a: int, b: int) -> int +# Находит наибольший общий делитель двух чисел. +# Идея: алгоритм Евклида. +# Пока b не равно 0, заменяем: +# a = b +# b = a % b +def gcd(a: int, b: int) -> int: + while b != 0: + a, b = b, a % b + return a + + +# 7. frequency_analysis(text: str, n: int) -> list +# Находит n самых частых слов в тексте. +# Игнорирует регистр и некоторые знаки препинания. +# Возвращает список кортежей: (слово, частота). +# Идея: +# 1. Переводим текст в нижний регистр +# 2. Удаляем знаки препинания +# 3. Разбиваем на слова +# 4. Считаем частоты слов +# 5. Сортируем по частоте по убыванию +def frequency_analysis(text: str, n: int) -> list: + text = text.lower() + + for ch in ",.!?:;()-": + text = text.replace(ch, " ") + + words = text.split() + counts = {} + + for word in words: + counts[word] = counts.get(word, 0) + 1 + + result = sorted(counts.items(), key=lambda x: x[1], reverse=True) + return result[:n] + + +# 8. lcm(a: int, b: int) -> int +# Находит наименьшее общее кратное двух чисел. +# Идея: используем формулу: +# lcm(a, b) = a * b // gcd(a, b) +def lcm(a: int, b: int) -> int: + return a * b // gcd(a, b) + +============================================================== + + 1) Цикл по строке `for ch in s:` +Зачем: пройти по строке посимвольно. +Когда: удалить повторы, посчитать буквы, собрать новую строку. +Что на вход: строка `s`. Что на выход: строка, число или `bool`. +Переменные: `s` — вся строка, `ch` — текущий символ. + +Пример: +```python +def remove_a(s: str) -> str: + result = "" + + for ch in s: + if ch != "a": + result += ch + + return result + +print(remove_a("abacada")) # bcd +``` + +Логика: +- идем по каждому символу; +- если символ не `"a"`, добавляем в `result`; +- в конце возвращаем новую строку. + +2) Цикл по списку `for x in arr:` +Зачем: пройти по всем элементам списка. +Когда: найти максимум, сумму, отфильтровать элементы. +Что на вход: список `arr`. Что на выход: число, список, `bool`. +Переменные: `arr` — список, `x` — текущий элемент. + +Пример: +```python +def only_positive(arr: list) -> list: + result = [] + + for x in arr: + if x > 0: + result.append(x) + + return result + +print(only_positive([-2, 5, 0, 7, -1])) # [5, 7] +``` + +Логика: +- идем по элементам; +- если элемент подходит, добавляем в новый список. + +3) Множество `set()` +Зачем: хранить только уникальные элементы и быстро проверять, встречался ли элемент раньше. +Когда: удалить дубликаты в строке или списке. +Что на вход: строка или список. Что на выход: строка/список без повторов. +Переменные: `seen` — множество уже встреченных элементов. + +Пример: +```python +def remove_duplicate_chars(s: str) -> str: + seen = set() + result = "" + + for ch in s: + if ch not in seen: + seen.add(ch) + result += ch + + return result + +print(remove_duplicate_chars("abacabad")) # abcd +``` + +Логика: +- если символ еще не встречался, добавляем его в `seen` и в ответ; +- если уже был, пропускаем. + +4) Словарь-счетчик `counts[x] = counts.get(x, 0) + 1` +Зачем: считать, сколько раз встречается каждый элемент. +Когда: частота слов, чисел, символов. +Что на вход: список, строка, слова текста. Что на выход: словарь частот или самый частый элемент. +Переменные: `counts` — словарь, `x` — текущий элемент. + +Пример: +```python +def count_numbers(arr: list) -> dict: + counts = {} + + for x in arr: + counts[x] = counts.get(x, 0) + 1 + + return counts + +print(count_numbers([1, 2, 1, 3, 2, 1])) # {1: 3, 2: 2, 3: 1} +``` + +Логика: +- для каждого элемента увеличиваем счетчик; +- если элемента еще нет, начинаем с 0. + +5) Цикл `while` +Зачем: повторять действия, пока выполняется условие. +Когда: НОД, работа с цифрами числа, два указателя. +Что на вход: зависит от задачи. Что на выход: зависит от задачи. +Переменные: обычно счетчик или значения, которые меняются в цикле. + +Пример: +```python +def gcd(a: int, b: int) -> int: + while b != 0: + a, b = b, a % b + return a + +print(gcd(18, 24)) # 6 +``` + +Логика: +- пока `b` не ноль, заменяем числа; +- когда `b` стал 0, ответ хранится в `a`. + +6) Преобразование числа в строку `str(n)` +Зачем: удобно работать с цифрами числа. +Когда: Армстронг, сумма цифр, палиндром числа. +Что на вход: число `n`. Что на выход: число, `bool` и т.д. +Переменные: `n` — число, `digits = str(n)` — строка с цифрами, `ch` — одна цифра как символ. + +Пример: +```python +def sum_of_digits(n: int) -> int: + total = 0 + + for ch in str(n): + total += int(ch) + + return total + +print(sum_of_digits(1234)) # 10 +``` + +Логика: +- переводим число в строку; +- идем по символам `"1"`, `"2"`, `"3"`, `"4"`; +- превращаем каждый символ обратно в число и суммируем. + +7) Сортировка `sorted(...)` +Зачем: упорядочить элементы или взять топ-N. +Когда: отсортировать числа, слова по частоте, результаты. +Что на вход: список или `dict.items()`. Что на выход: отсортированный список. +Переменные: `arr` — список, `x` — элемент, `x[1]` — второй элемент кортежа. + +Пример: +```python +def top_words(counts: dict) -> list: + return sorted(counts.items(), key=lambda x: x[1], reverse=True) + +print(top_words({"cat": 3, "dog": 2, "bird": 1})) +# [('cat', 3), ('dog', 2), ('bird', 1)] +``` + +Логика: +- `counts.items()` дает пары `(слово, частота)`; +- `key=lambda x: x[1]` значит сортировать по частоте; +- `reverse=True` — по убыванию. + +8) Два указателя +Зачем: эффективно обрабатывать два отсортированных списка. +Когда: пересечение, слияние, сравнение отсортированных списков. +Что на вход: два списка `a` и `b`. Что на выход: обычно новый список. +Переменные: `i` — индекс в первом списке, `j` — индекс во втором. + +Пример: +```python +def intersection_of_sorted(a: list, b: list) -> list: + i = 0 + j = 0 + result = [] + + while i < len(a) and j < len(b): + if a[i] == b[j]: + result.append(a[i]) + i += 1 + j += 1 + elif a[i] < b[j]: + i += 1 + else: + j += 1 + + return result + +print(intersection_of_sorted([1, 2, 3, 4], [2, 4, 6])) # [2, 4] +``` + +Логика: +- сравниваем текущие элементы двух списков; +- если равны — добавляем в ответ и двигаем оба указателя; +- если один меньше — двигаем только его; +- так не нужен двойной цикл, и алгоритм работает быстро. + + +