[프로그래머스] 신고 결과 받기 - defaultdict

zunzero·2022년 8월 23일
0

알고리즘(파이썬)

목록 보기
33/54

https://school.programmers.co.kr/learn/courses/30/lessons/92334
문제 이해는 그닥 어렵지 않다.
아이디어를 떠올리기도 그닥 어렵지 않았다.
신고한 사람과 신고 받은 사람을 사전 자료형을 사용해 이리저리 볶으면 해답이 나올 것이 뻔히 보이는 문제였다.

기존 사전 자료형을 이용해 문제를 풀어보니, 치명적인 오류가 발생했다.
muzi가 frodo와 neo를 신고한 경우에 대해서 알아보자.
내가 원했던 건 {'muzi' : 'frodo', 'muzi' : 'neo'} 라던가, {'muzi' : {'
frodo', 'neo'} 와 같은 형식이었다.
기존 사전 자료형을 사용하게 되면 위와 같은 결론을 얻을 수 없었다.

result = {}
result['muzi'] = 'frodo'
result['muzi'] = 'neo'

print(result)

위 소스코드의 결과는 {'muzi' : 'neo'}이다.
너무나 당연한 결과인데 파이썬에 익숙하지 않다보니 이런 문제를 겪었다.

이러한 문제를 해결하기 위해 구글링해 본 결과 collections의 defaultdict 클래스를 알게 되었다.

from collections import defaultdict

def solution(id_list, report,k):
    answer = []
    # 중복 신고 제거
    report = list(set(report))
    # user별 신고한 id 저장
    user = defaultdict(set)
    # user별 신고당한 횟수 저장
    cnt = defaultdict(int)
	
    for r in report:
        # report의 첫번째 값은 신고자id, 두번째 값은 신고당한 id
        a,b = r.split()
        # 신고자가 신고한 id 추가
        user[a].add(b)
        # 신고당한 id의 신고 횟수 추가
        cnt[b] += 1

    for i in id_list:
        result = 0
        # user가 신고한 id가 k번 이상 신고 당했으면, 받을 메일 추가
        for u in user[i]:
            if cnt[u]>=k:
                result +=1
        answer.append(result)
    return answer

defaultdict 생성자에 넣는 값이 중요하다.
set, list, int 등이 될 수가 있는데 아래는 예제이다.

a = defaultdict(int)
print(a['a'])	# 0 -> 기본 값 0
print(a)	# defaultdict(<class 'int'>, {'a': 0})
a['a'] += 99
print(a['a])	# 99

b = defaultdict(list)
b['a'].append(30)
b['a'].append(40)
b['b'].append(10)
print(b)	# defaultdict(<class 'list'>, {'a': [30, 40], 'b': [10]})
b['b'].append(10)
print(b)	# defaultdict(<class 'list'>, {'a': [30, 40], 'b': [10, 10]})

c = defaultdict(set)
c['a'].add(10)
c['a'].add(20)
c['b'].add(30)
print(c)	# defaultdict(<class 'set'>, {'a': {10, 20}, 'b': {30}})
c['b'].add(30)
print(c)	# defaultdict(<class 'set'>, {'a': {10, 20}, 'b': {30}})

정답 코드에서 set 자료형을 사용한 이유는 중복을 허용하지 않기 때문이다.
정말 유용하다!!

아래는 해당 문제에 대해 좋아요를 가장 많이 받은 솔루션이다.
따로 외부 라이브러리나 모듈 사용 없이 깔끔한 코드인 것 같다.

def solution(id_list, report, k):
    answer = [0] * len(id_list)    
    # 유저 별로 신고 당한 횟수를 기록하기 위한 사전 자료형
    reports = {x : 0 for x in id_list}	# {'muzi': 0, 'frodo': 0, 'apeach': 0, 'neo': 0}

	# 유저 별로 신고 당한 횟수를 기록
    for r in set(report):
        reports[r.split()[1]] += 1

	# 메일 수신 횟수 기록
    for r in set(report):
        if reports[r.split()[1]] >= k:
            answer[id_list.index(r.split()[0])] += 1

    return answer
profile
나만 읽을 수 있는 블로그

0개의 댓글