Algorithm/코딩테스트
[백준 2730] 오늘은 OS 숙제 제출일
이숨인
2024. 8. 26. 16:49
🍉문제
🍉문제 해석
숙제 마감일과 제출일이 주어졌을 때, 제출일이 마감일에 비해 얼마나 이전인지 또는 이후인지를 판단하고, 결과를 적절히 출력하는 문제이다.
** 제출일에는 연도가 명시되지 않기 때문에, 가장 가까운 연도를 추정하여 비교를 수행하도록 하였다!
이 부분이 가장 까다로웠던 부분인 듯 하다.
🍉문제 접근법
1. 윤년과 월별 일수 처리
- 윤년을 고려하여 월별 일수를 정확히 계산해야 했다.
- 2월의 경우, 윤년에 따라 28일 또는 29일을 반환하는 것을 잊지 말자!
- days_in_month 함수로 구현하였다.
thirty_days_month = [4, 6, 9, 11]
thirty_one_days_month = [1, 3, 5, 7, 8, 10, 12]
def days_in_month(month, year):
if month in thirty_days_month:
return 30
elif month in thirty_one_days_month:
return 31
else: # February
if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0):
return 29
else:
return 28
2. 날짜를 일수로 변환
- 비교를 위해 날짜를 연도(year),월(month)을 기준으로 총 일수로 변환해야 한다.
- 이 과정에서 모든 연도의 일수를 누적하도록 하였다
- date_to_days_total 함수를 통해 구현하였다.
def date_to_days_total(day, month, year):
days = 0
# 1. (현재 연도의 이전 연도까지)연도에 대해 일수를 누적한다. 윤년을 고려한다
for y in range(1, year):
days += 366 if y % 4 == 0 and (y % 100 != 0 or y % 400 == 0) else 365
# 2. 현재 연도의 월에 대해 일수를 누적한다. 앞에서 정의한 days_in_month함수를 통해 윤년을 고려하도록 하였다.
for m in range(1, month):
days += days_in_month(m, year)
# 3. 현재 월에 일수를 더한다
days += day
return days
3. 날짜를 문자열로 변환
월, 일, 연도를 문자열로 변환하여 반환하는 함수를 구현하였다.
월과 일의 선행 0은 자동으로 제거된다
def datetime_to_string(month, day, year):
return f'{month}/{day}/{year}'
4. 제출일과 마감일 비교
handle_dates 함수는 제출일과 마감일을 비교하여, 제출일이 마감일에 비해 얼마나 이른지 또는 늦은지를 판단하고,
상황에 따라 다른 메시지를 반환하는 역할을 한다.
def handle_dates(deadline_str, submission_str):
d_month, d_day, d_year = map(int, deadline_str.split('/'))
s_month, s_day = map(int, submission_str.split('/'))
# 마감일과 제출일을 일수로 변환
total_deadline = date_to_days_total(d_day, d_month, d_year)
# 제출일의 연도를 추정하여 두 가지 경우를 처리
possible_years = [d_year - 1, d_year, d_year + 1]
closest_submission_date = None
closest_gap = float('inf')
for year in possible_years:
total_submission = date_to_days_total(s_day, s_month, year)
gap = total_submission - total_deadline
if abs(gap) < abs(closest_gap):
closest_gap = gap
closest_submission_date = (s_month, s_day, year)
# 날짜 차이 계산
s_month, s_day, s_year = closest_submission_date
gap = closest_gap
if gap > 0:
if 1 < gap <= 7:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAYS AFTER'
elif gap == 1:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAY AFTER'
else:
return "OUT OF RANGE"
elif gap < 0:
gap = -gap
if 1 < gap <= 7:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAYS PRIOR'
elif gap == 1:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAY PRIOR'
else:
return "OUT OF RANGE"
else:
return "SAME DAY"
이번 문제의 핵심 로직을 담고있는 handle_dates는 위와 같다. 이제 코드를 분석해보자
1) 함수 정의 및 매개변수
- deadline_str: 마감일을 나타내는 문자열로, MM/DD/YYYY 형식이다
- submission_str: 제출일을 나타내는 문자열로, MM/DD 형식이다
total_deadline = date_to_days_total(d_day, d_month, d_year)
2)마감일을 일수로 변환
total_deadline = date_to_days_total(d_day, d_month, d_year)
3) 제출일의 연도를 추정하여 비교
possible_years = [d_year - 1, d_year, d_year + 1]
closest_submission_date = None
closest_gap = float('inf')
- 제출일의 연도는 명시되지 않으므로, 마감일의 전년도, 해당 연도, 다음 년도를 가능한 연도로 설정하여 제출일을 비교하여 결정한다.
- closest_submission_date는 가장 가까운 제출일을 저장할 변수이다
- closest_gap은 마감일과 제출일 간의 차이를 저장하며, 초기값으로 무한대를 설정하여 이후에 실제 차이로 대체하도록 한다.
4) 가능한 연도에 대한 제출일 비교
for year in possible_years:
total_submission = date_to_days_total(s_day, s_month, year)
gap = total_submission - total_deadline
if abs(gap) < abs(closest_gap):
closest_gap = gap
closest_submission_date = (s_month, s_day, year)
- 각 가능한 연도에 대해 제출일을 일수로 변환하고, 마감일과의 차이를 계산한다
- 가장 작은 차이를 가진 제출일을 closest_submission_date에 저장한다
5) 날짜 차이 계산 및 결과 반환
s_month, s_day, s_year = closest_submission_date
gap = closest_gap
- 최종적으로 가장 가까운 제출일을 s_month, s_day, s_year로 저장하고, 차이를 gap으로 설정한다.
- 제출일이 마감일보다 늦은 경우 , 제출일이 마감일보다 이른 경우, 마감일과 제출일이 같은 경우 세 가지 경우로 구분하여 출력한다
if gap > 0: #제출일이 마감일보다 늦은 경우
if 1 < gap <= 7:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAYS AFTER'
elif gap == 1:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAY AFTER'
else:
return "OUT OF RANGE"
elif gap < 0: #제출일이 마감일보다 이른 경우
gap = -gap
if 1 < gap <= 7:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAYS PRIOR'
elif gap == 1:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAY PRIOR'
else:
return "OUT OF RANGE"
else: #마감일과 제출일이 같은 경우
return "SAME DAY"
🍉전체 코드
# 월별 일수와 윤년 처리
thirty_days_month = [4, 6, 9, 11]
thirty_one_days_month = [1, 3, 5, 7, 8, 10, 12]
def days_in_month(month, year):
if month in thirty_days_month:
return 30
elif month in thirty_one_days_month:
return 31
else: # February
if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0):
return 29
else:
return 28
def date_to_days_total(day, month, year):
days = 0
# Add days for years
for y in range(1, year):
days += 366 if y % 4 == 0 and (y % 100 != 0 or y % 400 == 0) else 365
# Add days for months in the current year
for m in range(1, month):
days += days_in_month(m, year)
# Add days in the current month
days += day
return days
def datetime_to_string(month, day, year):
# Convert to string without leading zeros
return f'{month}/{day}/{year}'
def handle_dates(deadline_str, submission_str):
d_month, d_day, d_year = map(int, deadline_str.split('/'))
s_month, s_day = map(int, submission_str.split('/'))
# 마감일과 제출일을 일수로 변환
total_deadline = date_to_days_total(d_day, d_month, d_year)
# 제출일의 연도를 추정하여 두 가지 경우를 처리
possible_years = [d_year - 1, d_year, d_year + 1]
closest_submission_date = None
closest_gap = float('inf')
for year in possible_years:
total_submission = date_to_days_total(s_day, s_month, year)
gap = total_submission - total_deadline
if abs(gap) < abs(closest_gap):
closest_gap = gap
closest_submission_date = (s_month, s_day, year)
# 날짜 차이 계산
s_month, s_day, s_year = closest_submission_date
gap = closest_gap
if gap > 0:
if 1 < gap <= 7:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAYS AFTER'
elif gap == 1:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAY AFTER'
else:
return "OUT OF RANGE"
elif gap < 0:
gap = -gap
if 1 < gap <= 7:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAYS PRIOR'
elif gap == 1:
return f'{datetime_to_string(s_month, s_day, s_year)} IS {gap} DAY PRIOR'
else:
return "OUT OF RANGE"
else:
return "SAME DAY"
# 입력을 처리하는 부분
N = int(input())
results = []
for _ in range(N):
deadline, submission = input().split()
result = handle_dates(deadline, submission)
results.append(result)
# 결과 출력
for result in results:
print(result)