diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..62c89355 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/for_challenges.py b/for_challenges.py index 997754da..b0e466ae 100644 --- a/for_challenges.py +++ b/for_challenges.py @@ -1,9 +1,10 @@ # Задание 1 # Необходимо вывести имена всех учеников из списка с новой строки +print('Задание 1') names = ['Оля', 'Петя', 'Вася', 'Маша'] -# ??? - +for name in names: + print(name) # Задание 2 # Необходимо вывести имена всех учеников из списка, рядом с именем показать количество букв в нём @@ -11,13 +12,15 @@ # Оля: 3 # Петя: 4 +print('\nЗадание 2') names = ['Оля', 'Петя', 'Вася', 'Маша'] -# ??? - +for name in names: + print(f'{name}: {len(name)}') # Задание 3 # Необходимо вывести имена всех учеников из списка, рядом с именем вывести пол ученика +print('\nЗадание 3') is_male = { 'Оля': False, # если False, то пол женский 'Петя': True, # если True, то пол мужской @@ -25,8 +28,9 @@ 'Маша': False, } names = ['Оля', 'Петя', 'Вася', 'Маша'] -# ??? - +for name in names: + gender = ("woman", "man")[is_male[name]] + print(f'{name}: {gender}') # Задание 4 # Даны группу учеников. Нужно вывести количество групп и для каждой группы – количество учеников в ней @@ -35,23 +39,28 @@ # Группа 1: 2 ученика. # Группа 2: 4 ученика. +print('\nЗадание 4') groups = [ ['Вася', 'Маша'], ['Вася', 'Маша', 'Саша', 'Женя'], ['Оля', 'Петя', 'Гриша'], ] -# ??? - +print(f'Всего {len(groups)} группы.') +for n, group in enumerate(groups, start=1): + print(f'Группа {n}: {len(group)} ученика.') # Задание 5 # Для каждой пары учеников нужно с новой строки перечислить учеников, которые в неё входят # Пример вывода: # Группа 1: Вася, Маша -# Группа 2: Оля, Петя, Гриша +# Группа 2: Оля, Петя, Гри +print('\nЗадание 5') groups = [ ['Вася', 'Маша'], ['Оля', 'Петя', 'Гриша'], ['Вася', 'Маша', 'Саша', 'Женя'], ] -# ??? \ No newline at end of file +for n, group in enumerate(groups, start=1): + print(f'Группа {n}:', end=' ') + print(*group, sep=", ") diff --git a/for_dict_challenges.py b/for_dict_challenges.py index 96062ebc..7a73d453 100644 --- a/for_dict_challenges.py +++ b/for_dict_challenges.py @@ -1,3 +1,15 @@ +def make_freq_dict(students_list): + names_list = list([x['first_name'] for x in students_list]) + freq_dict = {name: names_list.count(name) for name in set(names_list)} + return freq_dict + + +def find_items_with_max_values(freq_dict): + max_freq = max(freq_dict.values()) + max_freq_names = [name for name, freq in freq_dict.items() if freq == max_freq] + return ', '.join(max_freq_names), max_freq + + # Задание 1 # Дан список учеников, нужно посчитать количество повторений каждого имени ученика # Пример вывода: @@ -5,6 +17,8 @@ # Маша: 2 # Петя: 2 +print('Задание 1') + students = [ {'first_name': 'Вася'}, {'first_name': 'Петя'}, @@ -12,22 +26,30 @@ {'first_name': 'Маша'}, {'first_name': 'Петя'}, ] -# ??? +name_freq_dict = make_freq_dict(students) +for name, freq in name_freq_dict.items(): + print(f'{name}: {freq}') # Задание 2 # Дан список учеников, нужно вывести самое часто повторящееся имя # Пример вывода: # Самое частое имя среди учеников: Маша + +print('\nЗадание 2') + students = [ {'first_name': 'Вася'}, {'first_name': 'Петя'}, {'first_name': 'Маша'}, {'first_name': 'Маша'}, {'first_name': 'Оля'}, + {'first_name': 'Оля'} ] -# ??? +names_freq_dict = make_freq_dict(students) +result = find_items_with_max_values(names_freq_dict) +print(f'Чаще всего встречаются имена: {result[0]} ({result[1]} раз(a))') # Задание 3 # Есть список учеников в нескольких классах, нужно вывести самое частое имя в каждом классе. @@ -35,6 +57,8 @@ # Самое частое имя в классе 1: Вася # Самое частое имя в классе 2: Маша +print('\nЗадание 3') + school_students = [ [ # это – первый класс {'first_name': 'Вася'}, @@ -44,15 +68,19 @@ {'first_name': 'Маша'}, {'first_name': 'Маша'}, {'first_name': 'Оля'}, - ],[ # это – третий класс + ], [ # это – третий класс {'first_name': 'Женя'}, {'first_name': 'Петя'}, {'first_name': 'Женя'}, {'first_name': 'Саша'}, ], ] -# ??? +print('Самые частые имена по классам / число повторений:') +for num, group in enumerate(school_students, start=1): + group_names_freq_dict = make_freq_dict(group) + result = find_items_with_max_values(group_names_freq_dict) + print(f'\t№{num}: {result[0]} / {result[1]}') # Задание 4 # Для каждого класса нужно вывести количество девочек и мальчиков в нём. @@ -60,6 +88,8 @@ # Класс 2a: девочки 2, мальчики 0 # Класс 2б: девочки 0, мальчики 2 +print('\nЗадание 4') + school = [ {'class': '2a', 'students': [{'first_name': 'Маша'}, {'first_name': 'Оля'}]}, {'class': '2б', 'students': [{'first_name': 'Олег'}, {'first_name': 'Миша'}]}, @@ -72,8 +102,19 @@ 'Миша': True, 'Даша': False, } -# ??? +for group in school: + group_name = group['class'] + gender_composition = { + 'f': 0, + 'm': 0 + } + + for student in group['students']: + key = ('f', 'm')[is_male[student['first_name']]] + gender_composition[key] += 1 + + print(f'Класс {group_name}: девочки {gender_composition["f"]}, мальчики {gender_composition["m"]}') # Задание 5 # По информации о учениках разных классов нужно найти класс, в котором больше всего девочек и больше всего мальчиков @@ -81,6 +122,7 @@ # Больше всего мальчиков в классе 3c # Больше всего девочек в классе 2a +print('\nЗадание 5') school = [ {'class': '2a', 'students': [{'first_name': 'Маша'}, {'first_name': 'Оля'}]}, {'class': '3c', 'students': [{'first_name': 'Олег'}, {'first_name': 'Миша'}]}, @@ -91,5 +133,27 @@ 'Олег': True, 'Миша': True, } -# ??? + +def count_group_gender_composition(group, gender_name_dict): + gender_composition = [0, 0] + for student in group['students']: + gender_composition[gender_name_dict[student['first_name']]] += 1 + return gender_composition + + +school_gender_by_class = dict() +girls_by_class = dict() +boys_by_class = dict() + +for group in school: + class_name = group['class'] + girls_by_class[class_name], boys_by_class[class_name] = count_group_gender_composition(group, is_male) + +school_gender_by_class['девочек'] = girls_by_class +school_gender_by_class['мальчиков'] = boys_by_class + + +for gender, breakdown in school_gender_by_class.items(): + result = find_items_with_max_values(breakdown) + print(f'Больше всего {gender} в классах: {result[0]}') diff --git a/for_dict_challenges_bonus.py b/for_dict_challenges_bonus.py index 9f35a0a0..7270e598 100644 --- a/for_dict_challenges_bonus.py +++ b/for_dict_challenges_bonus.py @@ -35,6 +35,7 @@ import datetime import lorem +from typing import Dict, Tuple, List def generate_chat_history(): @@ -66,5 +67,201 @@ def generate_chat_history(): return messages +def make_freq_dict_by_key(messages_list: List[Dict], key: str) -> Dict: + """ + Принимает список словарей с информацией по сообщениям в чате + и ключ, по которому необходимо осуществить подбор данных. + Например, если передать ключ "sent_by", + то функуия сначала создаст список, сотоязий из id пользователей, кто написал каждое сообщение, + а потом создаст частотный словарь, где ключами будут id пользователей, + а значениями - количество сообщений, написанных ими в чате. + :param messages_list: список словарей с информацией по сообщениям в чате + :param key: ключ, + по которому необходимо осуществить подбор данных по сообщениям + :return: частотный словарь + """ + some_list = [message[key] for message in messages_list if message[key]] + freq_dict = {value: some_list.count(value) for value in set(some_list)} + return freq_dict + + +def find_items_with_max_values(freq_dict: Dict) -> Tuple[List, int]: + """ + Функция определяет ключи с максимальным значением. + :param freq_dict: словарь, значения в котором являются целыми числами + :return: кортеж из двух элементов. + Первый элемент - список ключей с максимальным значением + Второй элемент - максимальное значение (целое число) + """ + max_freq = max(freq_dict.values()) + max_freq_items = [name for name, freq in freq_dict.items() if freq == max_freq] + return max_freq_items, max_freq + + +def users_wrote_max(messages_list: List[Dict]) -> Tuple[List, int]: + """ + Функция вычисляет пользователей, которые написали максимальное количество сообщений в чате + :param messages_list: список словарей с информацией по сообщениям в чате + :return кортеж из двух элементов. + Первый элемент - список id пользователей. + Второй элемент - максимальное число сообщений + """ + return find_items_with_max_values(make_freq_dict_by_key(messages_list, 'sent_by')) + + +def users_got_max_replies_by_one_message(messages_list: List[Dict]) -> Tuple[List, int]: + """ + Функция вычисляет пользователей, сообщения которых получили максимальное количество ответов + (к одному сообщению) + :param messages_list: список словарей с информацией по сообщениям в чате + :return: кортеж из двух элементов. + Первый элемент - список id пользователей + Второй элемент - максимальное число ответов на сообщение + """ + messages_with_max_replies = find_items_with_max_values(make_freq_dict_by_key(messages_list, 'reply_for')) + users_got_max_replies = [message['sent_by'] for message in messages_list if + message['id'] in messages_with_max_replies[0]] + max_replies_by_one_message = messages_with_max_replies[1] + return users_got_max_replies, max_replies_by_one_message + + +def users_got_max_replies_total(messages_list: List[Dict]) -> Tuple[List, int]: + """ + Функция вычисляет пользователей, + которые суммарно получили максимальное количество ответов на все свои сообщения + :param messages_list: список словарей с информацией по сообщениям в чате + :return: кортеж из двух элементов. + Первый элемент - список id пользователей + Второй элемент - максимальное число ответов + """ + replies_cnt_by_message = make_freq_dict_by_key(messages_list, 'reply_for') + messages_with_reply_info = dict() + for message_with_reply in replies_cnt_by_message.keys(): + message_info = dict() + for message in messages_list: + if message['id'] == message_with_reply: + message_info['sent_by'] = message['sent_by'] + message_info['replies_cnt'] = replies_cnt_by_message[message_with_reply] + messages_with_reply_info[message_with_reply] = message_info + + total_replies_cnt_by_users = dict() + for message in messages_with_reply_info.values(): + if message['sent_by'] in total_replies_cnt_by_users: + total_replies_cnt_by_users[message['sent_by']] += message['replies_cnt'] + else: + total_replies_cnt_by_users[message['sent_by']] = message['replies_cnt'] + + return find_items_with_max_values(total_replies_cnt_by_users) + + +def users_wrote_messages_seen_by_max_users(messages_list: List[Dict]) -> Tuple[List, int]: + """ + Функция вычисляет пользователей, + сообщения которых увидело максимальное количество уникальных пользователей + :param messages_list: список словарей с информацией по сообщениям в чате + :return: кортеж из двух элементов. + Первый элемент - список id пользователей + Второй элемент - максимальное число уникальных пользователей, увидевших сообщения + """ + sent_by_seen_by_dict = dict() + + for message in messages_list: + sent_by = message['sent_by'] + seen_by = message['seen_by'] + if sent_by not in sent_by_seen_by_dict: + sent_by_seen_by_dict[sent_by] = [] + if sent_by in sent_by_seen_by_dict: + sent_by_seen_by_dict[sent_by].extend(seen_by) + + for item in sent_by_seen_by_dict: + unique_ids = set(sent_by_seen_by_dict[item]) + sent_by_seen_by_dict[item] = len(unique_ids) + + return find_items_with_max_values(sent_by_seen_by_dict) + + +def count_messages_by_time_period(messages_list: List[Dict], start_hour: int, finish_hour: int) -> int: + """ + Функуия считает количество сообщений, написанных в определённые часы + :param messages_list: список словарей с информацией по сообщениям в чате + :param start_hour: час начала + :param finish_hour: час окончания + :return: количество сообщений, написанных в определённые часы + """ + count = len([message for message in messages_list if start_hour <= message['sent_at'].hour < finish_hour]) + return count + + +def find_prime_time_period(messages_list, *hours: int) -> str: + """ + Функуия определяет, в какой из периодов времени в сутках написано больше всего сообщений в чате + :param messages_list: список словарей с информацией по сообщениям в чате + :param hours: часы, определяющие временные границы периодов для подсчёта сообщений + :return: строка с информацией о периоде времени, когда написано максимальное количество сообщений + """ + time_periods = [] + time_periods.extend([(0, hours[0]), (hours[-1], 24)]) + for n in range(len(hours)): + if n < len(hours) - 1: + time_periods.append((hours[n], hours[n + 1])) + + messages_by_time_dict = {time_period: count_messages_by_time_period(messages_list, time_period[0], time_period[1]) + for time_period in time_periods} + prime_time_info = find_items_with_max_values(messages_by_time_dict) + + match prime_time_info[0][0]: + case (0, 12): + return 'утром (до 12 часов)' + case (12, 18): + return 'днём (12-18 часов)' + case (18, 24): + return 'вечером (после 18 часов)' + + return f'c {prime_time_info[0][0][0]} до {prime_time_info[0][0][1]} часов' + + +def messages_with_longest_threads(message_list: List[Dict]) -> Tuple[List, int]: + """ + Функция вычисляет сообщения, которые стали началом для самых длинных тредов (цепочек ответов) + :param message_list: список словарей с информацией по сообщениям в чате + :return: кортеж из двух элементов. + Первый элемент - список id сообщений + Второй элемент - максимальное число сообщений в треде + """ + reply_messages = [message for message in message_list if message['reply_for']] + reply_messages_ids = [message['id'] for message in reply_messages] + reply_chain_length_by_message = dict() + + for message in reply_messages: + count = 2 + parent_message_id = message['reply_for'] + while parent_message_id in reply_messages_ids: + count += 1 + parent_message_id = reply_messages[reply_messages_ids.index(parent_message_id)]['reply_for'] + reply_chain_length_by_message[parent_message_id] = count + + return find_items_with_max_values(reply_chain_length_by_message) + + if __name__ == "__main__": - print(generate_chat_history()) + messages = generate_chat_history() + + print(f'1. Пользователи с id {users_wrote_max(messages)[0]} написал(и) сообщений больше всех ' + f'({users_wrote_max(messages)[1]} шт.)') + + print(f'2а. Сообщения с максимальным количеством ответов были отправлены пользователями ' + f'с id {users_got_max_replies_by_one_message(messages)[0]} ' + f'({users_got_max_replies_by_one_message(messages)[1]} ответа(-ов))') + + print(f'2б. Больше всего ответов (суммарно на все свои сообщения)' + f' получили пользователи с id {users_got_max_replies_total(messages)[0]} ' + f'({users_got_max_replies_total(messages)[1]} ответа(-ов))') + + print(f'3. Id пользователей, сообщения которых видело больше всего уникальных пользователей: ' + f'{users_wrote_messages_seen_by_max_users(messages)[0]}') + + print(f'4. Больше всего сообщений в чате {find_prime_time_period(messages, 12, 18)}') + + print(f'5. Id сообщений, которые стали началом для самых длинных тредов ' + f'{list(map(str, messages_with_longest_threads(messages)[0]))} ' + f'(длина треда - {messages_with_longest_threads(messages)[1]} сообщений)') \ No newline at end of file diff --git a/string_challenges.py b/string_challenges.py index 856add2d..950a0c71 100644 --- a/string_challenges.py +++ b/string_challenges.py @@ -1,28 +1,43 @@ # Вывести последнюю букву в слове +print('Задание 1') word = 'Архангельск' -# ??? +print(word[-1]) # Вывести количество букв "а" в слове +print('\nЗадание 2') word = 'Архангельск' -# ??? +word = word.lower() +print(word.count('а')) # Вывести количество гласных букв в слове +print('\nЗадание 3') +rus_vowels = 'аоуэыяёеюи' word = 'Архангельск' -# ??? +word_vowels_cnt = 0 +for letter in word.lower(): + word_vowels_cnt += letter in rus_vowels +print(f'Количество гласных букв в слове "{word}": {word_vowels_cnt}') # Вывести количество слов в предложении +print('\nЗадание 4') sentence = 'Мы приехали в гости' -# ??? +print(len(sentence.split())) # Вывести первую букву каждого слова на отдельной строке +print('\nЗадание 5') sentence = 'Мы приехали в гости' -# ??? +words = sentence.split() +for word in words: + print(word[0]) # Вывести усреднённую длину слова в предложении +print('\nЗадание 6') sentence = 'Мы приехали в гости' -# ??? \ No newline at end of file +words_lengths = [len(word) for word in sentence.split()] +avg_word_length = sum(words_lengths) / len(words_lengths) +print(avg_word_length)