문제 설명
고객의 약관 동의를 얻어서 수집된 1~n
번으로 분류되는 개인정보 n
개가 있습니다. 약관 종류는 여러 가지 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있습니다. 당신은 각 개인정보가 어떤 약관으로 수집됐는지 알고 있습니다. 수집된 개인정보는 유효기간 전까지만 보관 가능하며, 유효기간이 지났다면 반드시 파기해야 합니다.
예를 들어, A라는 약관의 유효기간이 12 달이고, 2021년 1월 5일에 수집된 개인정보가 A약관으로 수집되었다면 해당 개인정보는 2022년 1월 4일까지 보관 가능하며 2022년 1월 5일부터 파기해야 할 개인정보입니다. 당신은 오늘 날짜로 파기해야 할 개인정보 번호들을 구하려 합니다.
모든 달은 28일까지 있다고 가정합니다.
오늘 날짜를 의미하는 문자열 today
, 약관의 유효기간을 담은 1차원 문자열 배열 terms
와 수집된 개인정보의 정보를 담은 1차원 문자열 배열 privacies
가 매개변수로 주어집니다. 이때 파기해야 할 개인정보의 번호를 오름차순으로 1차원 정수 배열에 담아 return
하도록 solution
함수를 완성해 주세요.
제한사항
today
는YYYY.MM.DD
형태로 오늘 날짜를 나타냅니다.- 1 ≤
terms의 길이
≤ 20 terms
의 원소는 “약관 종류 유효기간” 형태의 약관 종류와 유효기간을 공백 하나로 구분한 문자열입니다.- 약관 종류는 A~Z중 알파벳 대문자 하나이며,
terms
배열에서 약관 종류는 중복되지 않습니다. - 유효기간은 개인정보를 보관할 수 있는 달 수를 나타내는 정수이며, 1 이상 100 이하입니다.
- 1 ≤
privacies의 길이
≤ 100 privacies[i]
는i+1
번 개인정보의 수집 일자와 약관 종류를 나타냅니다.privacies
의 원소는 “날짜 약관 종류” 형태의 날짜와 약관 종류를 공백 하나로 구분한 문자열입니다.- 날짜는
YYYY.MM.DD
형태의 개인정보가 수집된 날짜를 나타내며,today
이전의 날짜만 주어집니다. privacies
의 약관 종류는 항상terms
에 나타난 약관 종류만 주어집니다.today
와privacies
에 등장하는 날짜의YYYY
는 연도,MM
은 월,DD
는 일을 나타내며 점(.) 하나로 구분되어 있습니다.- 2000 ≤
YYYY
≤ 2022 - 1 ≤
MM
≤ 12MM
이 한 자릿수인 경우 앞에 0이 붙습니다.
- 1 ≤
DD
≤ 28DD
가 한 자릿수인 경우 앞에 0이 붙습니다.
- 파기해야 할 개인정보가 하나 이상 존재하는 입력만 주어집니다.
- 2000 ≤
분석
1번 문제는 문자열 처리, 기본 자료구조 등을 활용한 단순 구현 문제였습니다. 대략적인 흐름은 아래와 같습니다.
today
를 비교할 수 있는 형태로 변환terms
의 약관에 따라 접근 할 수 있는 자료 구조로 저장privacies
의 원소 별 개인정보 수집 일자를 계산할 수 있는 형태로 변환하고, 약관에 따라 만료일 계산- 비교할 수 있는 형태로 변환된
today
와 비교하여 만료 여부 확인
today
와 privacies
의 약관에 따라 계산된 개인 정보 수집 일자를 비교하는 처리가 필요했습니다. 따라서, 이 문제의 중요한 포인트는 문자열로 받은 날짜에 대한 처리였습니다.
terms
의 유효기간은 “월” 단위로만 입력을 받기 때문에 언어의 날짜 계산 툴을 활용해도 문제는 없을 것이라 생각되었습니다. 하지만 파이썬은 날짜에 “월"을 더하기 위해서 dateutil
을 사용해야 했는데, 이는 기본 라이브러리가 아니기 때문에 활용할 수 없었습니다.
다행히도 제한사항에 따라 월별 일수가 28일로 고정되어 있었기 때문에 날짜를 계산 처리는 여렵지 않다고 생각되었고, 필요한 기능을 직접 구현하기로 결정하였습니다.
처음에는 년, 월, 일을 가진 클래스를 구상했었는데 일, 월의 경우는 더해질 경우 올림이 발생하므로 처리가 조금 번거로웠습니다. 그리고, 날짜 비교를 위해 년, 월, 일 모두 비교해야 하므로 비교 처리도 비교적 복잡해 보였습니다.
문제에서 요구하는 결과는 해당 개인정보의 파기 여부를 확인하는 것 이었기 때문에, 단순 비교를 위해서 타임스탬프를 응용 하기로 했습니다.
결과
|
|
CustomTimeStamp
앞서 설명드린 내용 처럼 제약사항에 따른 총 일수를 이용해 비교하는 클래스를 구현하였습니다. 유닉스 타임스탬프와 달리 입력으로 받는 년, 월, 일 만 이용해서 총 일수를 계산하여 비교적 간단히 구현할 수 있었습니다.
__ge__
__ge__
매직 메소드를 이용해 >=
연산자 오버로딩을 하여 조금 더 깔끔하게 구현될 수 있도록 해봤습니다.
add
인스턴스 변수인 total
을 __addYearToDays
, __addMonthToDays
, __addDay
를 이용하여 일 수를 더합니다. 내외부에서 모두 사용되기 때문에 공통화를 위해 구현하였습니다.
__addYearToDays
, __addMonthToDays
, __addDay
상수를 통해 일수를 계산하여 total
에 저장합니다. 타임스탬프 계산 기준이 바뀔 경우 로직 변경이 필요할 수 있기 때문에 별도로 분리해서 구현해봤습니다.
strToCustomDate
입력을 편하게 처리하기 위한 정적 메소드로 datetime
패키지를 이용하여 문자열로 입력받은 일자를 년, 월, 일로 바꾸어 CustomTimeStamp
의 인스턴스를 반환하는 기능을 구현했습니다.
solution
privacies
를 순회하며 CustomTimeStamp
를 통해 만료일을 계산하고 오늘 날짜와 비교하는 방식으로 구현할 수 있었습니다.
끝으로
요구사항만 만족하도록 구현했다면 구조가 훨씬 단순해졌을텐데, 구현하다보니 욕심이 생겨 일을 크게 만들어 버렸네요.
하지만 입력되는 날짜 형식이 변경된다던가, 월 외에도 년, 일에 대해 날짜를 계산해야하는 처리가 추가되었다던가, 날짜 제한이 바뀌어 계산 처리가 바뀌어야 한다던가, 시간, 분, 초 처럼 처리되어야 하는 다른 단위가 추가된다던가 등 여러 변경사항이 있더라도 조금 더 대응하기 쉬워졌지 않았을까 생각해봅니다.
다 만들고 마무리 하다보니 년, 월, 일도 인스턴스 변수로 처리하면 더 좋았겠다는 생각도 드네요.
아무튼 도움이 되었기를 바라며, 끝까지 읽어주셔서 감사합니다 :)