Определение ближайшего дня рождения сотрудника
Задача: Сотрудники организации
Дан список сотрудников организации, в котором указаны их фамилии, имена и даты рождения. Напишите программу, которая определяет самого молодого сотрудника, празднующего свой день рождения в течение ближайших семи дней от текущей даты.
Формат входных данных На вход программе в первой строке подается текущая дата в формате DD.MM.YYYY, в следующей строке вводится натуральное число n — количество сотрудников, работающих в организации. В последующих n строках вводятся данные о каждом сотруднике: имя, фамилия и дата рождения, разделённые пробелом. Дата рождения указывается в формате DD.MM.YYYY.
Формат выходных данных Программа должна определить самого молодого сотрудника, празднующего свой день рождения в течение ближайших семи дней, и вывести его имя и фамилию, разделив пробелом. Если таких сотрудников нет, программа должна вывести текст:
Дни рождения не планируются Примечание 1. Гарантируется, что у всех сотрудников даты рождения различны.
Примечание 2. Например, для даты 01.11.2021 ближайшими семью днями являются:
02.11.2021, 03.11.2021, 04.11.2021, 05.11.2021, 06.11.2021, 07.11.2021, 08.11.2021
Написал два варианта
1 вариант
from datetime import datetime, timedelta
def find_youngest_birthday(employees, current_date):
# Преобразуем текущую дату в объект datetime
current_date = datetime.strptime(current_date, '%d.%m.%Y')
# Инициализируем переменные для хранения самого молодого сотрудника и его даты рождения
youngest_employee = None
youngest_age = None
youngest_birthday = None
# Перебираем всех сотрудников
for employee in employees:
# Преобразуем дату рождения сотрудника в объект datetime
birthday = datetime.strptime(employee['birthday'], '%d.%m.%Y')
# Проверяем, празднует ли сотрудник свой день рождения в течение ближайших семи дней
if (birthday.replace(year=current_date.year) - current_date).days >= 0 and (birthday.replace(year=current_date.year) - current_date).days <= 7:
# Рассчитываем возраст сотрудника на момент текущей даты
age = current_date.year - birthday.year
if current_date.month < birthday.month or (current_date.month == birthday.month and current_date.day < birthday.day):
age -= 1
# Если это самый молодой сотрудник, то обновляем переменные
if youngest_age is None or age < youngest_age:
youngest_employee = employee
youngest_age = age
youngest_birthday = birthday
elif age == youngest_age and birthday > youngest_birthday:
youngest_employee = employee
youngest_birthday = birthday
# Если найден хотя бы один сотрудник, празднующий свой день рождения в течение ближайших семи дней, то возвращаем его имя и фамилию
if youngest_employee:
return f"{youngest_employee['name']} {youngest_employee['surname']}"
else:
# Иначе возвращаем текст "Дни рождения не планируются"
return "Дни рождения не планируются"
# Читаем входные данные
current_date = input()
n = int(input())
employees = []
for _ in range(n):
name, surname, birthday = input().split()
employees.append({'name': name, 'surname': surname, 'birthday': birthday})
# Вызываем функцию и выводим результат
print(find_youngest_birthday(employees, current_date))
но при тесте 1
Test input:
14.11.2021
3
Иван Петров 16.11.1995
Петр Сергеев 14.11.1997
Сергей Романов 17.11.1994
Test output:
Петр Сергеев
вместо Иван Петров
2 вариант
from datetime import datetime, timedelta
# Функция для парсинга даты из строки
def parse_date(date_str):
return datetime.strptime(date_str, '%d.%m.%Y')
# Чтение текущей даты
current_date_str = input().strip()
current_date = parse_date(current_date_str)
# Определение диапазона дней
start_date = current_date + timedelta(days=1)
end_date = current_date + timedelta(days=7)
# Чтение количества сотрудников
n = int(input().strip())
# Список для хранения ближайших дней рождений
birthdays = []
# Обработка данных сотрудников
for _ in range(n):
employee_data = input().strip()
name, surname, birth_date_str = employee_data.split()
birth_date = parse_date(birth_date_str)
# Получаем день и месяц рождения, устанавливаем год на текущий
birth_day_month = birth_date.replace(year=current_date.year)
# Проверяем, попадает ли день рождения в диапазон
if start_date <= birth_day_month <= end_date:
birthdays.append((birth_day_month, name, surname))
# Если есть дни рождения, определяем самого молодого
if birthdays:
# Сортировка по дате рождения
birthdays.sort(key=lambda x: x[0]) # Сортируем по дате
# Вывод имен самого молодого в диапазоне
print(birthdays[0][1], birthdays[0][2]) # Молодой — это первый после сортировки
else:
print("Дни рождения не планируются")
при тесте 4
10.11.2021
5
Иван Петров 11.11.1995
Петр Сергеев 12.11.1992
Сергей Романов 13.11.1996
Роман Григорьев 14.11.1994
Григорий Иванов 15.11.1995
выводит Иван Петров вместо Сергея Романова
Ответы (2 шт):
Самый молодой - у которого дата рождения позже, а не раньше, поэтому во втором варианте нужно выбирать последнего после сортировки (или лямбду сортировки модифицировать, или reverse=True).
В первом, т.к. текущий день не учитывается, нужно строгое сравнение дня
if (birthday.replace(year=current_date.year) - current_date).days > 0
Вот ваш первый вариант, доработанный чтобы проходил тест.
from datetime import datetime
from dateutil.relativedelta import relativedelta
def find_youngest_birthday(employees, current_date):
# Преобразуем текущую дату в объект datetime
current_date = datetime.strptime(current_date, '%d.%m.%Y')
# Инициализируем переменные для хранения самого молодого сотрудника и его даты рождения
youngest_employee = None
youngest_age = None
youngest_birthday = None
# Перебираем всех сотрудников
for employee in employees:
# Преобразуем дату рождения сотрудника в объект datetime
birthday = datetime.strptime(employee['birthday'], '%d.%m.%Y')
# Проверяем, празднует ли сотрудник свой день рождения в течение ближайших семи дней
diff_date_in_days = (birthday.replace(year=current_date.year)-current_date).days
if diff_date_in_days < 0:
diff_date_in_days = (birthday.replace(year=current_date.year+1)-current_date).days
if 0 < diff_date_in_days <= 7:
# Рассчитываем возраст сотрудника на момент текущей даты
age = relativedelta(current_date, birthday).years
# Если это самый молодой сотрудник, то обновляем переменные
if youngest_age is None or age < youngest_age:
youngest_employee = employee
youngest_age = age
youngest_birthday = birthday
elif age == youngest_age and birthday > youngest_birthday:
youngest_employee = employee
youngest_birthday = birthday
# Если найден хотя бы один сотрудник, празднующий свой день рождения в течение ближайших семи дней, то возвращаем его имя и фамилию
if youngest_employee:
return f"{youngest_employee['name']} {youngest_employee['surname']}"
else:
# Иначе возвращаем текст "Дни рождения не планируются"
return "Дни рождения не планируются"
def test_find_youngest_birthday():
test_case_employees = [{'name': 'Иван', 'surname': 'Петров', 'birthday': '11.11.1995'},
{'name': 'Петр', 'surname': 'Сергеев', 'birthday': '12.11.1992'},
{'name': 'Сергей', 'surname': 'Романов', 'birthday': '13.11.1996'},
{'name': 'Роман', 'surname': 'Григорьев', 'birthday': '14.11.1994'},
{'name': 'Григорий', 'surname': 'Иванов', 'birthday': '10.11.1995'}
]
result = find_youngest_birthday(test_case_employees, '10.11.2021')
assert result == 'Сергей Романов'
test_find_youngest_birthday()
Но конечно, код можно сделать более простым и выразительным:
def find_youngest_birthday(employees, current_date):
# Преобразуем текущую дату в объект datetime
current_date = datetime.strptime(current_date, '%d.%m.%Y')
def get_diff_in_days(_employee, _current_date):
_birthday_as_date = datetime.strptime(_employee['birthday'], '%d.%m.%Y')
_employee['birthday'] = _birthday_as_date
result = (_birthday_as_date.replace(year=current_date.year)-_current_date).days
if result < 0:
result = (_birthday_as_date.replace(year=current_date.year+1)-_current_date).days
return result
# ищем сотрудников с датой рождения через 1-7 дней
employees_in_condition = [e for e in employees if 0< get_diff_in_days(e, current_date) <= 7]
# оставляем самого молодого
youngest_employee_in_condition = next(iter(sorted(employees_in_condition, key=lambda e: e['birthday'],reverse=True)), None)
return youngest_employee_in_condition or "Дни рождения не планируются"