문제: 프로그래머스: 개인정보 수집 유효기간

문제

아래 3개

  • today: 오늘 날짜를 의미하는 YYYY.MM.DD 형태의 문자열
  • terms: 약관의 유효기간을 <약관 유형 문자> <유효기간(월)> 형태로 문자열로 담은 1차원 배열
    • terms 배열 길이 범위: [1, 20]
    • terms에 있는 약관 유형은 중복되지 않음
    • 유효기간은 월 단위로, 범위 [1, 100] 범위를 가짐
  • privacies: 수집된 개인정보의 정보(<수집 날짜> <약관 유형> 형태의 문자열로 이루어진 값)가 담긴 1차원 문자열 배열
    • privacies 배열 길이 범위: [1, 100]
    • 수집 날짜는 YYYY.MM.DD 형태의 문자열로, 반드시 today보다 앞에(이전에) 옴
    • 수집 날짜 + 유효기간 = 오늘일 경우 해당 정보는 파기해야 하는 걸로 간주(예: 2020-02-22(수집 날짜) + 6개월 = 2020-08-22(오늘)일 경우 이 정보는 파기해야 하는 거로 간주) -가 입력으로 주어졌을 경우,

파기해야 하는 개인정보의 번호(인덱스 + 1)의 배열을 반환하는 문제.

접근

split

termsprivacies에 있는 정보들은 모두 2개의 다른 정보가 하나의 문자열로 합쳐진 형태로 들어온다. 즉, 각각의 정보를 뽑아낼 수 있게 분리를 해내야 했다.

KotlinJava와 똑같이 split을 사용할 수 있다. Map도 비슷하게 사용이 가능하니,

  1. MutableMap<String, Long> 인스턴스를 생성한다.
  2. terms 각각에 들어가 있는 유형과 유효기간을 분리 추출한다.
  3. 2의 그것에서 유형(String)을 key로, 유효기간(Long)을 value로 삼아 1의 그것에 넣는다.

Date

todayprivacies모두 날짜가 들어간다. 이걸 날짜 데이터로 뽑아내면 날짜 계산이 더 수월할 것이다. JavaLocalDateDateTimeFormatter를 사용하여 뽑아낼 수 있을 것이다. 이걸 이용해서…

  1. DateTimeFormatter.ofPattern 함수를 통해 형식을 yyyy.MM.dd로 정해주고,
  2. String today를 1의 그것을 거쳐 LocalDate로 바꿔준다.
  3. privacies 속 수집 날짜를 1의 그것을 거쳐 LocalDate로 바꿔준다.
  4. 3의 그것을 유형 별 유효기간과 합쳐(기간을 더해), 2의 그것이 이걸 넘어갔는지를 체크한다.

4의 그것은 두 부분으로 나눌 수 있는데,

  • 기간을 더하는 부분은 LocalDate의 plusMonths 함수를 통해 그 결과값을 구할 수 있다.
  • 위의 그것을 todayLocaldate가 넘어갔는지 확인하는 것은 LocalDateisBefore를 통해 확인할 수 있다. (isAfter도 있지만, todayLocalDate 버전이 위의 그것과 동일하더라도 파기 대상으로 간주하기에 isBefore의 반대를 취해야 했다.) 가 된다.

이 둘을 합쳐서…

todayDate: String `today`를 LocalDate로 바꾼 값
validMonths: 약관 유형 별로 가지는 유효기간(월 단위)을 MutableMap<String, Long>의 형태로 담은 것
invalidPrivacies: 파기해야 하는 약관 번호들을 모아두는 MutableList<Int>
 
privacies 요소 하나(each)마다 진행:
	dateCollected: each의 날짜 부분을 LocalDate로 바꾼 값
	monthsValidForPrivacy: each의 유형 부분을 key로 했을 때 이에 대응하는 `validMonths`에서의 value(유효 기간, 달 단위)
	만약 (dateCollected + monthsValidForPrivacy) <= todayDate라면:
		invalidPrivacies에 each의 인덱스 + 1의 값을 삽입
 
invalidPrivacies 반환

의 형태로 조합할 수 있을 것이다. 이걸 Kotlin 코드로 표현했을 땐 아래와 같다:

class Solution {
    fun solution(today: String, terms: Array<String>, privacies: Array<String>): IntArray {
        var monthsValid = mutableMapOf<String, Long>()
        var dateFormatter = DateTimeFormatter.ofPattern("yyyy.MM.dd")
        var splittedParts: List<String>
        val todayDate = LocalDate.parse(today, dateFormatter)
        var answer: MutableList<Int> = mutableListOf()
        
        for (each in terms) {
            splittedParts = each.split(" ")
            monthsValid.put(splittedParts[0], splittedParts[1].toLong())
        }
    
        
    
        for (i in privacies.indices) {
            splittedParts = privacies[i].split(" ")
            if (!todayDate.isBefore(LocalDate.parse(splittedParts[0], dateFormatter).plusMonths(monthsValid[splittedParts[1]]!!))) answer.add(i + 1)
        }
    
        return answer.toIntArray()
    }
}