Python/알고리즘 문제 풀이

[코테] 개인정보 수집 유효기간

마이구미+ 2023. 7. 31. 13:20

문제 링크

 

프로그래머스

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

programmers.co.kr

<로직 고민/>

  • 일단 한 달을 28일이라고 가정하는 거면 datetime 라이브러리를 못 쓰는건가??
  • terms는 딕셔너리 형태로 바꿔주는 게 좋을 것 같다
  • term를 for문으로 돌리면서 공백을 기준으로 split 한 후 0번째는 key값, 1번째는 value값으로 바꿔야지
  • 그 담에 privacies를 for문으로 돌리면서 각 약관에 맞는 term의 value 값을 더해주고 그걸 today랑 비교하면 되겠군
from datetime import datetime

def solution(today, terms, privacies):
    answer = []
    today = datetime.strptime(today, "%Y.%m.%d").date()
    
    # terms dict형으로 바꾸기
    terms_dict = {}
    for term in terms:
        key, value = term.split()
        terms_dict[key] = int(value)
    
    year, month, day = 0, 0, 0
    after_privacy = ""
    for idx, privacy in enumerate(privacies):       
        # 연도 및 월
        pre_month = int(privacy.split()[0].split(".")[1])
        month = pre_month + terms_dict[privacy.split()[1]]
        if month > 12 and month < 24:
            month -= 12
            year = int(privacy.split()[0].split(".")[0]) + 1
        elif month > 24:
            month -= 24
            year = int(privacy.split()[0].split(".")[0]) + 2
        else:
            year = int(privacy.split()[0].split(".")[0])
        
        # 일
        if int(privacy.split()[0].split(".")[2]) == 1:
            day = 28
            month -= 1
        else:
            day = int(privacy.split()[0].split(".")[2]) - 1
        
        after_privacy = str(year) + str(month) + str(day)
        after_privacy = datetime.strptime(after_privacy, "%Y%m%d").date()
        
        if today > after_privacy:
            answer.append(idx + 1)
    return answer
  • 이렇게 하니까 테스트 20개 중에 6개만 통과하고 나머지는 런타임에러가 난다
  • 뭔가 if문 예외처리가 잘못된 것 같다
  • 19번째 줄에 month가 24보다 작거나 같은 경우로 썼어야 했는데 잘못 썼다
  • 근데 그거 고쳐도 12개 테스트에서 런타임에러, 1개는 실패가 뜬다
  • 유효기간 제한사항을 잘못 봤다 ㅋㅋㅋ....
  • 유효기간이 최대 20개월인 줄 알았는데 약관의 최대 길이가 20개였고, 유효기간 최대 개월수는 100이었다 후..
from datetime import datetime

def solution(today, terms, privacies):
    ...
    for idx, privacy in enumerate(privacies):       
        # 연도 및 월
        month = int(privacy.split()[0].split(".")[1]) + terms_dict[privacy.split()[1]]
        year = int(privacy.split()[0].split(".")[0])
        if month > 12:
            year += month // 12
            month = month % 12
        
        ...
    return answer
  • 이렇게 수정했다
  • 근데 또 실패닷

  • 성공이 2개 늘긴 했는데...ㅋㅋㅋ후 다시 보자
  • 테스트케이스에 반례를 추가했더니 이제 알았다

  • 월, 일 자릿수를 안 맞춰준 게 문제였다
after_privacy = str(year) + str(month).zfill(2) + str(day).zfill(2)
  • 이렇게 수정 후 다시 코드를 실행했는데 아래와 같은 에러가 나왔다
ValueError: time data '20200009' does not match format '%Y%m%d'
  • day를 구할 때 day가 1이면 28로 바꾸고 month를 -1 하는 부분에서 틀린 것 같다
  • month가 원래 1인 경우에는 12로 바꾸고 연도도 바꿔주어야 하는데 그 처리가 미흡했다
  • 11번째 줄 아래에 아래 코드를 추가했더니 이제 테스트 14, 17에서만 실패한다
            if month % 12 == 0:
                month = 12
  • 또 다른 예외사항을 찾아야 한다....
  • 아.....month를 12로 나눴을 때 딱 떨어지는 경우 year도 조정해줘야 하는구나

  • 이 케이스를 추가하고 깨달았는데 month가 12로 나눴을 때 0으로 딱 떨어지면 year를 1개 빼줘야 한다
  • 수정했더니 드디어 통과....

<완성된 풀이/>

from datetime import datetime

def solution(today, terms, privacies):
    answer = []
    today = datetime.strptime(today, "%Y.%m.%d").date()
    
    # terms dict형으로 바꾸기
    terms_dict = {}
    for term in terms:
        key, value = term.split()
        terms_dict[key] = int(value)
    
    year, month, day = 0, 0, 0
    after_privacy = ""
    for idx, privacy in enumerate(privacies):                   
        # 연도 및 월
        year = int(privacy.split()[0].split(".")[0])
        month = int(privacy.split()[0].split(".")[1]) + terms_dict[privacy.split()[1]]
        if month > 12:
            year += month // 12
            month = month % 12
            if month % 12 == 0:
                year -= 1
                month = 12

        # 일
        if int(privacy.split()[0].split(".")[2]) == 1:
            day = 28
            if month == 1:
                month = 12
                year -= 1
            else:
                month -= 1
        else:
            day = int(privacy.split()[0].split(".")[2]) - 1
            
        after_privacy = str(year) + str(month).zfill(2) + str(day).zfill(2)
        after_privacy = datetime.strptime(after_privacy, "%Y%m%d").date()
        
        if today > after_privacy:
            answer.append(idx + 1)
    return answer

<다른 사람 풀이/>

- 천재풀이1

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
  • 와 진짜 어떻게 이런 생각을 하지..
  • 난 너무 무식하고 빙빙 돌아돌아 풀었네
  • split 남발한 것도 ㅋㅋㅋ슬라이싱으로 해결할 수 있는 걸 괜히 코드만 길어지게 split 엄청 썼네,,