NIRVANA

[level 1] 개인정보 수집 유효기간 본문

Coding test(Python3)/Programmers

[level 1] 개인정보 수집 유효기간

녜잉 2023. 9. 10. 15:42

문제

고객의 약관 동의를 얻어서 수집된 1~n번으로 분류되는 개인정보 n개가 있습니다. 약관 종류는 여러 가지 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있습니다. 당신은 각 개인정보가 어떤 약관으로 수집됐는지 알고 있습니다. 수집된 개인정보는 유효기간 전까지만 보관 가능하며, 유효기간이 지났다면 반드시 파기해야 합니다.

예를 들어, A라는 약관의 유효기간이 12 달이고, 2021년 1월 5일에 수집된 개인정보가 A약관으로 수집되었다면 해당 개인정보는 2022년 1월 4일까지 보관 가능하며 2022년 1월 5일부터 파기해야 할 개인정보입니다.
당신은 오늘 날짜로 파기해야 할 개인정보 번호들을 구하려 합니다.

모든 달은 28일까지 있다고 가정합니다.

다음은 오늘 날짜가 2022.05.19일 때의 예시입니다.

 

  • 첫 번째 개인정보는 A약관에 의해 2021년 11월 1일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.
  • 두 번째 개인정보는 B약관에 의해 2022년 6월 28일까지 보관 가능하며, 유효기간이 지나지 않았으므로 아직 보관 가능합니다.
  • 세 번째 개인정보는 C약관에 의해 2022년 5월 18일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.
  • 네 번째 개인정보는 C약관에 의해 2022년 5월 19일까지 보관 가능하며, 유효기간이 지나지 않았으므로 아직 보관 가능합니다.

따라서 파기해야 할 개인정보 번호는 [1, 3]입니다.

오늘 날짜를 의미하는 문자열 today, 약관의 유효기간을 담은 1차원 문자열 배열 terms와 수집된 개인정보의 정보를 담은 1차원 문자열 배열 privacies가 매개변수로 주어집니다. 이때 파기해야 할 개인정보의 번호를 오름차순으로 1차원 정수 배열에 담아 return 하도록 solution 함수를 완성해 주세요.

 

 

문제 풀이 접근법1

1) terms를 공백으로 나눈 뒤, 0번째 원소(약관)를 key로 1번째 원소(보관 기간)를 vaule로 하는 딕셔너리 dict_terms를 생성한다. 

2) privacies를 기준으로 for 문을 돌리며 각 원소의 9번째 자리까지(수집 날짜)를 key로 마지막 원소(약관)를 value 로 하는 딕셔너리 dict_pri를 생성한다. 

3) dict_pri를 list로 변환하여 각 원소 i,j 를 받아오며 for문을 반복한다. 기간은 연/월/일에 맞게 잘라서 사용하고, 약관의 유효기간은 j(value, 약관 저장되어 있음)를 key로 사용하여 dict_terms에서 가져온다. 

4) end_month와 dict_terms[j]를 합한 값이 12를 넘으면 year에 end_month에서 12를 나눈 몫을 더하고, end_month는 12를 나눈 나머지 값으로 정한다. 

5) end_day의 경우는 처음 정의할 때 -1을 하고, 만약 해당 값이 0이라면 end_month에 -1을 한 뒤, end_day를 28로 정의한다. 

6) end_year가 today의 년도 보다 작을 경우, 

end_year는 같으나 end_month가 today의 월보다 작을 경우, 

end_year와 end_month는 같으나 end_day가 today의 일보다 작을 경우 

해당 연도의 인덱스를 answer에 추가한다. 

def solution(today, terms, privacies):
    dict_terms = {}
    dict_pri = {}
    answer = []

    for i in terms:
        term = i.split(" ")
        dict_terms[term[0]] = term[1]

    for i in privacies:
        dict_pri[i[:10]] = i[-1]


    for i, j  in list(dict_pri.items()):
        end_month = int(i[5:7]) + int(dict_terms[j])
        end_year = int(i[:4])
        end_day = int(i[8:10]) -1


        if end_month > 12:
            end_year += end_month // 12
            end_month = end_month % 12


        if end_day == 0:
            end_month -=1
            end_day = 28


        if end_year < int(today[:4]):
            answer.append(list(dict_pri).index(i)+1)
        elif end_year == int(today[:4]) and end_month < int(today[5:7]):
            answer.append(list(dict_pri).index(i)+1) 
        elif end_year == int(today[:4]) and end_month == int(today[5:7]) and end_day < int(today[8:10]):
            answer.append(list(dict_pri).index(i)+1)
        

        
    return answer

10, 12, 13, 15, 16, 17, 18, 19, 20에서 실패했다. 

일단 10, 12, 15, 18, 20의 경우에는 privacies에 중복 케이스가 들어갈 수 있어서 그런거였다.

날짜를 key값으로 하고 있는데 중복은 안되니까..

 

 

문제 풀이 접근법2

-privacies에 중복을 허용하기 위해 dict_pri를 리스트로 변경하였다. 

-privacies의 원소들은 공백 문자를 기준으로 자른 뒤 리스트로 dict_pri에 추가하였다. 그렇게 dict_pir의 형태를 이중 리스트로 변경하고 인덱스로 접근했다. 

def solution(today, terms, privacies):
    dict_terms = {}
    dict_pri = []
    answer = []

    j = 1



    for i in terms:
        term = i.split(" ")
        dict_terms[term[0]] = term[1]

    for i in privacies:
        dict_pri.append(i.split())


    for i in dict_pri:

        end_month = int(i[0][5:7]) + int(dict_terms[i[1]])
        end_year = int(i[0][:4])
        end_day = int(i[0][8:10]) -1

        if end_month > 12:
            end_year += end_month // 12
            end_month = end_month % 12


        if end_day == 0:
            end_month -=1
            end_day = 28

        if end_year < int(today[:4]):
            answer.append(j)
        elif end_year == int(today[:4]) and end_month < int(today[5:7]):
            answer.append(j) 
        elif end_year == int(today[:4]) and end_month == int(today[5:7]) and end_day < int(today[8:10]):
            answer.append(j)

        j+=1


        
    return answer

테스트 케이스 17에서 실패했다. 

반례는 다음과 같았다. 

입력: "2020.12.17", ["A 12"], ["2010.01.01 A", "2019.12.17 A"] 일때, 두번째 케이스에서 month 부분이 0이 되었고, 2020년이 아닌 2021년이 되는 것을 확인했다(12+12 = 24로 실제로는 1년이지만 위의 코드에서는 2년을 더하게 되어서)

이런 이유로 모든 개인정보가 폐기해야 하지만 1번만 폐기하는 것으로 나왔다.

 

 

문제 풀이 접근법3

- end_month % 12 == 0이면 year에 -1을 해주었다. 

- month가 0이하이면 month를 다시 12로 설정해주었다.

def solution(today, terms, privacies):
    dict_terms = {}
    dict_pri = []
    answer = []

    j = 1



    for i in terms:
        term = i.split(" ")
        dict_terms[term[0]] = term[1]

    for i in privacies:
        dict_pri.append(i.split())


    for i in dict_pri:

        end_month = int(i[0][5:7]) + int(dict_terms[i[1]])
        end_year = int(i[0][:4])
        end_day = int(i[0][8:10]) -1

        if end_month > 12:
            end_year += (end_month // 12 ) 
            if end_month % 12 == 0:
                end_year -= 1
            end_month = end_month % 12

        if end_day == 0:
            end_month -=1
            end_day = 28

        if end_month <= 0:
            end_month = 12

        if end_year < int(today[:4]):
            answer.append(j)
        elif end_year == int(today[:4]) and end_month < int(today[5:7]):
            answer.append(j) 
        elif end_year == int(today[:4]) and end_month == int(today[5:7]) and end_day < int(today[8:10]):
            answer.append(j)

        j+=1


        
    return answer

 

 


 

다른 분들 문제 풀이 

def to_days(date):
    year, month, day = map(int, date.split("."))
    return year * 28 * 12 + month * 28 + day

def solution(today, terms, privacies):
    months = {v[0]: int(v[2:]) * 28 for v in terms}
    today = to_days(today)
    expire = [
        i + 1 for i, privacy in enumerate(privacies)
        if to_days(privacy[:-2]) + months[privacy[-1]] <= today
    ]
    return expire