새소식

⌨️ Algorithms/프로그래머스

[Python] 프로그래머스 Lv1_개인정보 수집 유효기간

2023. 1. 15. 00:19

  • -

https://school.programmers.co.kr/learn/courses/30/lessons/150370

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

  • 1~n번으로 분류되는 개인정보 n개
  • 약관 종류는 여러 가지 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있음
  • 각 개인정보가 어떤 약관으로 수집됐는지 알고 있음
  • 수집된 개인정보는 유효기간 전까지만 보관 가능하며, 유효기간이 지났다면 반드시 파기해야 함
  • ex) A라는 약관의 유효기간이 12 달이고, 2021년 1월 5일에 수집된 개인정보가 A약관으로 수집되었다면
    • 해당 개인정보는 2022년 1월 4일까지 보관 가능
    • 2022년 1월 5일부터 파기해야 할 개인정보
  • 오늘 날짜로 파기해야 할 개인정보 번호들을 구하려 함
  • 모든 달은 28일까지 있다고 가정
  • today: 오늘 날짜를 의미하는 문자열
  • terms: 약관의 유효기간을 담은 1차원 문자열 배열
  • privacies: 수집된 개인정보의 정보를 담은 1차원 문자열 배열
  • 파기해야 할 개인정보의 번호를 오름차순으로 1차원 정수 배열에 담아 return

제한사항

  • 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 ≤ 12
    • MM이 한 자릿수인 경우 앞에 0이 붙음
    • 1 ≤ DD ≤ 28
    • DD가 한 자릿수인 경우 앞에 0이 붙음
  • 파기해야 할 개인정보가 하나 이상 존재하는 입력만 주어짐

 

"""
입출력 예시)

today = "2022.05.19", terms = ["A 6", "B 12", "C 3"], privacies = ["2021.05.02 A", "2021.07.01 B", "2022.02.19 C", "2022.02.20 C"] -> [1, 3]
today = "2020.01.01", terms = ["Z 3", "D 5"], privacies = ["2019.01.01 D", "2019.11.15 Z", "2019.08.02 D", "2019.07.01 D", "2018.12.28 Z"] -> [1, 4, 5]
"""

 

# today = "2022.05.19", terms = ["A 6", "B 12", "C 3"], privacies = ["2021.05.02 A", "2021.07.01 B", "2022.02.19 C", "2022.02.20 C"] -> [1, 3]

# 오늘 날짜 -> 2022.05.19

# 약관 종류: A, 유효기간: 6달
# 약관 종류: B, 유효기간: 12달
# 약관 종류: C, 유효기간: 3달

# 번호: 1, 개인정보 수집 일자: 2021.05.02, 약관 종류: A
# 번호: 2, 개인정보 수집 일자: 2021.07.01, 약관 종류: B
# 번호: 3, 개인정보 수집 일자: 2022.02.19, 약관 종류: C
# 번호: 4, 개인정보 수집 일자: 2022.02.20, 약관 종류: C

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

# => 파기해야 할 개인정보 번호는 [1, 3]

 

 

## 의사코드 ##

# terms의 약관 종류와 privacies의 약관 종류는 같음
# 모든 달은 28일까지만 있음

# terms를 딕셔너리로 변환 -> {약관 종류: 유효기간}

# 날짜: "YYYY.MM.DD" 형태
# 날짜.split('.') 해서 년도, 월, 일로 나눠서 계산


# for i in range(len(privacies)):
# 각 번호별로 보관 가능한 날짜를 구함
# 보관 가능한 날짜 = 개인정보 수집한 달 + 약관 종류의 유효기간, 일자 -1 
#     달 수 > 12 이면 (년도 + 1, 달 - 12)
#     만약 개인정보 수집 일자의 일이 1이면 (달 수 -1) + 일자: 28


#  보관 가능 날짜 < today 이면 파기 o 
# (-> 보관 가능 날짜가 today와 같거나 today보다 크면 아직 보관 가능)

# return answer # 오름차순 정렬

 

 

 

첫 번째 시도

 

def solution(today, terms, privacies):
    answer = []
    terms_dic = {}
    y, m, d = map(int, today.split('.'))
    # terms를 딕셔너리로 변환
    for t in terms:
        t_type, t_month = t.split()
        terms_dic[t_type] = int(t_month)
        
    for i in range(len(privacies)):
        p_date, p_type = privacies[i].split()
        p_y, p_m, p_d = map(int, p_date.split('.'))

        # 보관 가능 날짜 계산
        p_m += terms_dic[p_type] # 수집한 달 + 유효기간(달)
        # 개인정보 수집 일자의 일이 1인 경우
        if p_d == 1:
            p_m -= 1
            p_d == 28
        # 개인정보 수집 일자의 일이 1이 아닌 경우
        else:
            p_d -= 1 # 수집한 일 - 1
        # 보관 가능한 달이 12보다 크면
        while p_m > 12:
            p_y += 1
            p_m -= 12

        # today와 보관 가능 날짜 비교
        if p_y > y: # 보관 가능 년도가 today의 년도보다 큰 경우
            continue
        elif p_y == y: # 보관 가능 년도가 today의 년도와 같은 경우
            if p_m > m: # 보관 가능 달이 today의 달보다 크면
                continue
            elif p_m == m: # 보관 가능 달이 today의 달과 같으면 
                if p_d >= d: # 보관 가능 일이 today의 일보다 크거나 같은 경우
                    continue
        
        # 보관 가능 날짜가 today보다 작은 경우(이미 지난 경우)
        answer.append(i+1) # i의 순서대로 삽입되기 때문에 자동으로 오름차순 정렬
    return answer

-> 추가 테스트 케이스 2개 실패 (테스트 5, 테스트 13)

 

 

 

두 번째 시도

 

def solution(today, terms, privacies):
    answer = []
    terms_dic = {}
    y, m, d = map(int, today.split('.'))
    # terms를 딕셔너리로 변환
    for t in terms:
        t_type, t_month = t.split()
        terms_dic[t_type] = int(t_month)
        
    for i in range(len(privacies)):
        p_date, p_type = privacies[i].split()
        p_y, p_m, p_d = map(int, p_date.split('.'))

        # 보관 가능 날짜 계산
        p_m += terms_dic[p_type] # 수집한 달 + 유효기간(달)

        # 보관 가능한 달이 12보다 크면
        while p_m > 12:
            p_y += 1
            p_m -= 12
        
        # 개인정보 수집 일자의 일이 1인 경우
        if p_d == 1:
            # 보관 가능 날짜가 1월 1일인 경우 
            if p_m == 1:
                p_y -= 1
                p_m == 12
                p_d == 28
            else:
                p_m -= 1
                p_d == 28
        # 개인정보 수집 일자의 일이 1이 아닌 경우
        else:
            p_d -= 1 # 수집한 일 - 1

        # today와 보관 가능 날짜 비교
        if p_y > y: # 보관 가능 년도가 today의 년도보다 큰 경우
            continue
        elif p_y == y: # 보관 가능 년도가 today의 년도와 같은 경우
            if p_m > m: # 보관 가능 달이 today의 달보다 크면
                continue
            elif p_m == m: # 보관 가능 달이 today의 달과 같으면 
                if p_d >= d: # 보관 가능 일이 today의 일보다 크거나 같은 경우
                    continue
        
        # 보관 가능 날짜가 today보다 작은 경우(이미 지난 경우)
        answer.append(i+1) # i의 순서대로 삽입되기 때문에 자동으로 오름차순 정렬
    return answer

-> 보관 가능 날짜가 1월 1일인 경우 추가

-> 추가 테스트 케이스 3개 실패 (테스트 5, 테스트 13, 테스트 15)

 

  • ex) 보관 가능 날짜가 1월 1일인 경우
    • 개인정보 수집 일자: 2020.08.01
    • 유효기간: 5달
    • -> 2021.01.00 (일자 -1 까지 계산하면)
      • => 2020.12.28 까지로 바꿔줘야 함

 

  • 과정 확인
"""
today: 2022.05.19 

번호: 1
개인정보 수집 일자: 2021.05.02
유효기간: 6
보관 가능 날짜: 2021 11 1
------------------------------------------------------------
번호: 2
개인정보 수집 일자: 2021.07.01
유효기간: 12
보관 가능 날짜: 2022 6 1
------------------------------------------------------------
번호: 3
개인정보 수집 일자: 2022.02.19
유효기간: 3
보관 가능 날짜: 2022 5 18
------------------------------------------------------------
번호: 4
개인정보 수집 일자: 2022.02.20
유효기간: 3
보관 가능 날짜: 2022 5 19
------------------------------------------------------------
[1, 3]
"""

-> 번호 2의 보관 가능 날짜가 틀림

 

'번호 2의 보관 가능 날짜: 2022 6 28' 로 나왔어야 함

    -> 'p_d == 28' 이 부분이 적용되지 않아서 틀림

       => 변수의 값을 바꾸려고 했던 것이기 때문에 'p_d == 28'이 아닌 'p_d = 28'로 작성했어야

 

 

  • 변수에 저장된 값 바꾸기
# '=' 사용
d = 1
if d == 1:
  d = 28
d # -> 28
# cf) '==' 사용
d = 1
if d == 1:
  d == 28
d # -> 1
# -> 값이 바뀌지 않음

 

 

 

통과한 코드

 

  • 1) 두 번째 시도 코드 수정
def solution(today, terms, privacies):
    answer = []
    terms_dic = {}
    y, m, d = map(int, today.split('.'))
    # terms를 딕셔너리로 변환
    for t in terms:
        t_type, t_month = t.split()
        terms_dic[t_type] = int(t_month)
        
    for i in range(len(privacies)):
        p_date, p_type = privacies[i].split()
        p_y, p_m, p_d = map(int, p_date.split('.'))

        # 보관 가능 날짜 계산
        p_m += terms_dic[p_type] # 수집한 달 + 유효기간(달)

        # 보관 가능한 달이 12보다 크면
        while p_m > 12:
            p_y += 1
            p_m -= 12
        
        # 개인정보 수집 일자의 일이 1인 경우
        if p_d == 1:
            # 보관 가능 날짜가 1월 1일인 경우 
            if p_m == 1:
                p_y -= 1
                p_m += 11 # 달을 12월로 변환
                p_d += 27 # 일을 28일로 변환
            else:
                p_m -= 1
                p_d += 27 # 일을 28일로 변환
        # 개인정보 수집 일자의 일이 1이 아닌 경우
        else:
            p_d -= 1 # 수집한 일 - 1

        # today와 보관 가능 날짜 비교
        if p_y > y: # 보관 가능 년도가 today의 년도보다 큰 경우
            continue
        elif p_y == y: # 보관 가능 년도가 today의 년도와 같은 경우
            if p_m > m: # 보관 가능 달이 today의 달보다 크면
                continue
            elif p_m == m: # 보관 가능 달이 today의 달과 같으면 
                if p_d >= d: # 보관 가능 일이 today의 일과 같거나 큰 경우
                    continue
        
        # 보관 가능 날짜가 today보다 작은 경우(이미 지난 경우)
        answer.append(i+1) # i의 순서대로 삽입되기 때문에 자동으로 오름차순 정렬
    return answer

-> 보관 가능 날짜가 1월 1일인 경우, 달 + 11, 일 + 27로 변환하고 보관 가능 일이 today의 일과 같거나 큰 경우로 적용

 

 

과정 확인

"""
today: 2022.05.19 

번호: 1
개인정보 수집 일자: 2021.05.02
유효기간: 6
보관 가능 날짜: 2021 11 1
------------------------------------------------------------
번호: 2
개인정보 수집 일자: 2021.07.01
유효기간: 12
보관 가능 날짜: 2022 6 28
------------------------------------------------------------
번호: 3
개인정보 수집 일자: 2022.02.19
유효기간: 3
보관 가능 날짜: 2022 5 18
------------------------------------------------------------
번호: 4
개인정보 수집 일자: 2022.02.20
유효기간: 3
보관 가능 날짜: 2022 5 19
------------------------------------------------------------
[1, 3]
"""

-> '번호 2의 보관 가능 날짜: 2022 6 28' 로 제대로 적용됨

 

 

 

 

  • 2) 다른 풀이
    • -> 보관 가능 날짜를 계산할 때, (일 - 1) 없이 진행
def solution(today, terms, privacies):
    answer = []
    terms_dic = {}
    y, m, d = map(int, today.split('.'))
    # terms를 딕셔너리로 변환
    for t in terms:
        t_type, t_month = t.split()
        terms_dic[t_type] = int(t_month)
        
    for i in range(len(privacies)):
        p_date, p_type = privacies[i].split()
        p_y, p_m, p_d = map(int, p_date.split('.'))

        # 보관 가능 날짜 계산
        p_m += terms_dic[p_type] # 수집한 달 + 유효기간(달)

        # 보관 가능한 달이 12보다 크면
        while p_m > 12:
            p_y += 1
            p_m -= 12

        # today와 보관 가능 날짜 비교
        if p_y > y: # 보관 가능 년도가 today의 년도보다 큰 경우
            continue
        elif p_y == y: # 보관 가능 년도가 today의 년도와 같은 경우
            if p_m > m: # 보관 가능 달이 today의 달보다 크면
                continue
            elif p_m == m: # 보관 가능 달이 today의 달과 같으면 
                if p_d > d: # 보관 가능 일이 today의 일보다 큰 경우
                    continue
        
        # 보관 가능 날짜가 today보다 작은 경우(이미 지난 경우)
        answer.append(i+1) # i의 순서대로 삽입되기 때문에 자동으로 오름차순 정렬
    return answer

-> 개인정보 수집 일자의 일이 1인 경우 삭제, 보관 가능 날짜를 계산할 때 (일 - 1) 없이 진행, 보관 가능 일이 today의 일보다 크거나 같은 경우에서 큰 경우만 continue로 변경

 

 

과정 확인

today: 2022.05.19 

번호: 1
개인정보 수집 일자: 2021.05.02
유효기간: 6
보관 가능 날짜: 2021 11 2
------------------------------------------------------------
번호: 2
개인정보 수집 일자: 2021.07.01
유효기간: 12
보관 가능 날짜: 2022 7 1
------------------------------------------------------------
번호: 3
개인정보 수집 일자: 2022.02.19
유효기간: 3
보관 가능 날짜: 2022 5 19
------------------------------------------------------------
번호: 4
개인정보 수집 일자: 2022.02.20
유효기간: 3
보관 가능 날짜: 2022 5 20
------------------------------------------------------------
[1, 3]

 

 

 

 

 

참고) 

 

https://velog.io/@sbs524/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91-%EC%9C%A0%ED%9A%A8%EA%B8%B0%EA%B0%84-%ED%8C%8C%EC%9D%B4%EC%8D%AC-Lv.1

 

[프로그래머스] 개인정보 수집 유효기간 (파이썬) - Lv.1

https://school.programmers.co.kr/learn/courses/30/lessons/150370문제의 조건을 꼼꼼하게 확인하여 하나도 빠짐없이 구현하는게 포인트약관의 종류를 딕셔너리 타입으로 저장각 privacies마다 날짜와 연도를 구하

velog.io

 

https://velog.io/@corngang/python-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%BD%94%ED%85%8C-level1.-%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91-%EC%9C%A0%ED%9A%A8%EA%B8%B0%EA%B0%84

 

[python] 프로그래머스 코테 - level1. 개인정보 수집 유효기간

문제 > 고객의 약관 동의를 얻어서 수집된 1~n번으로 분류되는 개인정보 n개가 있습니다. 약관 종류는 여러 가지 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있습니다. 당신은 각 개인

velog.io

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다!