Python/Coding Test

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

semperparatus 2024. 2. 13. 11:48

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

 

프로그래머스

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

programmers.co.kr


코드

def solution(today, terms, privacies):
    valid = {}
    answer = []
    
    to_year, to_month, to_day = map(int, today.split('.'))
    
    for i in terms:
        a, b = i.split()
        valid[a] = int(b)
        
    for idx, j in enumerate(privacies):
        cal, te = j.split()
        val_year, val_month, val_day = map(int, cal.split('.'))
        
        # 유효기간이 1~100달인 것을 고려해서 코드를 작성해야 함 !
        val_year += valid[te] // 12
        val_month += valid[te] % 12
        val_day -= 1
        
        # 월이 12를 넘어가는 경우
        if val_month > 12:
            val_year += 1
            val_month -= 12
            
        # 일이 0이 되는 경우
        if val_day == 0:
            val_month -= 1
            val_day = 28

        if (val_year < to_year) or (val_year == to_year and (val_month < to_month or (val_month == to_month and val_day < to_day))):
            answer.append(idx+1)
            continue
            
    return answer

풀이

 작성한 코드를 간단하게 설명하자면 valid 딕셔너리에 입력 받은 약관 종류와 유효기간을 각각 key, value로 하도록 저정한다. 그리고 입력받은 개인정보를 for문을 돌면서 유효기간과 현재 날짜를 비교하여 파기해야 할 개인정보의 번호를 저장한다.

 코드를 작성하면서 어려웠던 부분은 크게 2가지가 있다.

 1번째는 입력값으로 주어지는 유효기간의 범위이다. 주어진 범위는 1 이상 100 이하이므로 그 값을 12로 나눈 몫과 나머지를 이용해 년도와 달을 조정해주어야 한다. 범위를 제대로 확인하지 않고 단순히 범위가 12보다 작거나 같을 것이라고 생각하여 작성하였다. 앞으로 문제를 풀 때 주어지는 제한사항을 꼼꼼히 확인하자. 

 2번째는 유효기간과 현재 날짜를 비교하는 if문이다. 날짜의 크기를 비교하는 문제이며 이는 아래와 같은 경우의 수로 나누어 생각할 수 있다.

 (1) 유효기간 년도가 현재 년도보다 작은 경우 -> 파기해야 함 

 (2) 유효기간 년도와 현재 년도 같음, 유효기간 달이 현재 달보다 작음 -> 파기해야 함

 (3) 유효기간 년도와 현재 년도 같음, 유효기간 달이 현재 달과 같음, 유효기간 일이 현재 일보다 작음 -> 파기해야 함

 생각해보면 당연한 비교이지만 조건을 작성해줄 때 세심하게 생각하지 않는다면 반례를 놓칠 수 있기에 주의해야 할 것 같다.


다른 코드 & 풀이

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

def solution(today, terms, privacies):
    # 약관 및 유효기간 딕셔너리
    standard = {i[0] : int(i[2:]) * 28 for i in terms}
    expire = [
        idx + 1 for idx, privacy in enumerate(privacies)
        if to_days(privacy[:-2]) + standard[privacy[-1]] <= to_days(today)
    ]
    
    return expire

 

프로그래머스에서 다른 풀이를 참고하던 중 꼭 이해하고 넘어가면 좋을 것 같은 코드 풀이가 있어 짚고 넘어가고자 한다.

년, 월, 일의 다양한 경우를 따져주어야 했던 나의 코드와 달리 년, 월, 일을 일로 변환하여 해당 일 수만 비교해주면 되는 코드이다. to_days는 주어진 날짜를 일 수로 변환하는 함수이다. 해당 코드를 보며 꼭 기억해야 할 점은 아래와 같다.

 1번째는 리스트 내포이다. 파이썬에서 for문과 if문을 한 라인에 작성하여 코드를 직관적으로 만들고 실행 속도를 높여주는 기법이며, 사용방식은 아래와 같다.

리스트명 = [표현식 for 변수 in 반복 가능한 대상]
리스트명 = [표현식 for 변수 in 반복 가능한 대상 if 조건문]

 

리스트 뿐만 아니라 딕셔너리에서도 사용 가능하므로 유용하게 사용해보도록 하자.

 2번째는 슬라이싱이다. 이 때 음수를 이용하면 변수의 뒤부터 슬라이싱할 수 있는데 위 코드에서 privacy[:-2]의 경우 맨 처음부터 -3 인덱스까지 슬라이싱해주는 코드이다. 슬라이싱 할 때 음수 인덱스를 자주 사용해보지 않아서 생소하게 느껴졌고 다음에도 사용할 수 있도록 익혀두어야겠다.