본문 바로가기

학습 노트/알고리즘 (Python)

99클럽 - 신고 결과 받기, 개인정보 수집 유효기간

신고 결과받기

 

프로그래머스

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

programmers.co.kr

아이디어

이전에 풀어봤던 문제다.
당시엔 각각 딕셔너리로 만들어 이 둘을 연결 지어 풀었던 것 같은데 아마 관계형 데이터베이스를 생각했던 것 같다.
알다시피 관계형 데이터베이스는 관리가 쉬운 거지 그리 효율적인 데이터 베이스는 아니기도 하고,
이번에는 데이터 처리 과정에서 예외처리로 의미 없는 연산의 수를 줄이는 방법을 선택했다.

유의해서 봐야 할 조건은 다음과 같다.

  • 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
  • 자기 자신을 신고하는 경우는 없습니다.

풀이

def solution(id_list, report, k):
    answer = [0]*len(id_list)
    rlist = []
    udict = {}
    
    for val in id_list:
        udict[val] = [0, []]
    
    for val in report:
        val = val.split()
        
        if val[1] in udict[val[0]][1] or val[1] == val[0]:
            pass
        else:
            udict[val[0]][1].append(val[1])
            udict[val[1]][0] += 1
        
            if udict[val[1]][0] >= k and val[1] not in rlist:
                rlist.append(val[1])
    
    for idx, data in enumerate(udict):
        udict[data][1] = set(udict[data][1])
        
        for target in rlist:
            if target in udict[data][1]:
                answer[idx] += 1
    
    return answer

udit의 구조는 id를 key로 사용하고, '신고 누적 횟수', '신고 아이디 배열'을 value로 사용한다.
index 접근은 가독성이 나쁠 뿐이지 효율이 나쁘지는 않으니 무서워하지 말자.

신고 내역을 순회하되 예외 조건인 '중복 신고'와 '셀프 신고'에 대해 불필요한 연산을 하지 않도록 조치해 속도를 높였다.
또한 계정 정지를 판단하는 과정도 순회 중에 진행해 id_list가 1000개가 되는 최악의 조건에서 재탐색 과정을 거치지 않도록 조치했다.

아마 신경 쓰지 않으면 딱 걸렸을 거다. 😅

개인정보 수집 유효기간

 

프로그래머스

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

programmers.co.kr

아이디어

아마 Python의 날짜 관련된 패키지를 사용하면 쉽게 해결할 수 있을 거라고 생각한다.
하지만 이번에도 별도의 import 없이 도전해 본다.

처음 사용한 접근 방법은 다음과 같다.

  • 월의 합을 구한다.
  • 월의 합을 기준으로 연을 증가시킨다.
  • 월의 합을 기준으로 월을 계산한다.
  • 오늘의 날짜와 비교한다.

위와 같이 참 간단해 보이지만 주의해야 할 부분이 있다.

  • 월의 합을 구해 연과 월을 계산하면 나머지와 몫을 사용하게 되는데 12의 배수일 때 나머지가 0이 된다.

편하자고 몫과 나머지를 사용했더니 되려 신경 써야 할 점이 늘어나게 된다. 
만들어 놓고 이건 아니다 싶어 while로 바꿨다.

날짜 비교 자체는 매우 간단한데 28일이고 뭐고 그냥 다 떼어서 예외처리 해 주면 된다.

풀이

def solution(today, terms, privacies):
    answer = []
    t_table = {}
    t_year, t_month, t_day = map(int, today.split('.'))

    for term in terms:
        name, due = term.split()
        t_table[name] = int(due)

    case = list(t_table.keys())

    for idx, target in enumerate(privacies):
        temp = target.split()
        year, month, day = map(int, temp[0].split('.'))
        
        for name in case:
            if temp[1] == name:
                month += t_table[name]
                
                while True:
                    if month > 12:
                        year += 1
                        month -= 12
                    else:
                        break

        if t_year > year:
            answer.append(idx + 1)
        elif (year == t_year) and (t_month > month):
            answer.append(idx + 1)
        elif (year == t_year) and (t_month == month) and (t_day >= day):
            answer.append(idx + 1)            

    return answer

나... while 좀 좋아하는지도 모르겠다.