노교수는 지금까지 서울사이버대학교 빅데이터·정보보호학과와 인공지능학과, 컴퓨터공학과 등에서 개의 수업을 진행하였다. 수업을 들었던 학생들을 회상하던 어느 날, 노교수는 자신의 수업을 개 이상 들은 학생이 몇 명인지 궁금해졌다.
수업과 학생의 수가 너무 많아 한눈에 들어오지 않았던 노교수는, 당신에게 분석을 의뢰했다. 각 수업을 들은 학생들의 학번이 주어질 때, 조건을 만족하는 학생의 수를 구하자.
첫 번째 줄에 , 이 차례대로 주어진다.
두 번째 줄부터 개의 줄에 걸쳐 각 수업에 대한 정보 개가 순서대로 주어진다.
번 수업의 정보는 두 개의 줄로 이뤄진다. 첫 번째 줄에 과목의 수강생 수 , 두 번째 줄에 번 수업을 들은 학생들의 학번 개가 공백 하나로 구분되어 주어진다.
학번은 숫자 8개로 구성되며, 항상 로 시작한다. 한 수업에 동일한 사람이 중복되어 있는 경우는 주어지지 않는다.
첫 번째 줄에 개 이상의 수업을 들은 학생의 수를 출력한다.
서울사이버대학교에서 한 반의 학생수는 최대 명이고, 학부생의 학번은 로 시작한다.
from collections import defaultdict
N, M = map(int, input().split())
student_counts = defaultdict(int)
for _ in range(N):
K_i = int(input())
student_ids = list(map(int, input().split()))
for student_id in student_ids:
student_counts[student_id] += 1
result = sum(1 for count in student_counts.values() if count >= M)
print(result)
이번 문제 풀면서 느낀 건 대략적으로 어떻게 접근해야 할 지는 잘 알고 있는데, 어떤 기능을 통해서 풀어야 하는지를 잘 모르는 것 같았다.
딕셔너리 이용해서 받아오면 되는데.. 그래서 어떤 함수를 써야하는지? 계속 이 과정만 반복하다 답답해서 풀이를 조금 더 상세하게 써보기로 했다.
먼저 N과 M을 받아온다. 그 다음 줄에서는 2 × N 줄에서 각 수업의 학생 수와 해당 학번 목록을 읽어온다고 했다.
N, M = map(int, input().split())
각 수업의 학생 수와 해당 학번을 sys.stdin.readline()
을 통해 입력 받아야하나? 그러면 각 라인을 기준으로 키와 값을 저장하려면 어떻게 해야하지? 이렇게 고민만 하다가 찾은게 defaultdict
였다.
student_counts = defaultdict(int)
for _ in range(N):
K_i = int(input())
student_ids = list(map(int, input().split()))
for student_id in student_ids:
student_counts[student_id] += 1
새롭게 알게된 내용에 적을 예정이지만 괄호 안의 형태로 딕셔너리를 초기화한다고 한다. 수업 개수 N 만큼 수업을 들은 학생 수와 그 학생들의 학번 리스트를 입력 받는다.
그리고 student_ids
에는 20240001과 같은 학번들이 들어있을 것이고 그 학생들이 수강 중인 수업을 세어야 하니까 student_counts[student_id] += 1
형태로 작성한다.
특히 이 부분이 이해가 잘 안 되었는데 리스트 형태로 저장되어 있는 각 학번들에게 count 값을 준다고 생각하면 되는 것 같다. 우리가 자주 쓰는 count += 1
을 떠올려 보자.
result = sum(1 for count in student_counts.values() if count >= M)
모든 학생들의 수강 횟수 중에서 M개 이상 수업을 들은 학생의 수만 세어야 하므로, 만족하는 학생들에게 1을 부여하고 sum()
을 통해 더하여 result
를 출력하면 된다.
count = 0
for value in student_counts.values():
if value >= M:
count += 1
print(count)
간결한 코드라 이해가 잘 안 되었는데, 풀어서 보면 이해가 잘 된다!
collections
: Python에서 데이터 구조와 관련된 고급 자료형을 제공한다. list
, dict
, set
, tuple
을 보완할 수 있다.
defaultdict()
: 딕셔너리와 유사하지만 존재하지 않는 키에 접근할 때 기본값을 자동으로 설정한다. int
로 설정하면 기본 값이 0이 되고, list
로 설정하면 기본 값은 리스트 형태가 된다. 특정 키에 값을 누적하거나 갱신할 때 유용하다.
from collections import defaultdict
# 기본값이 0인 defaultdict 생성
dd = defaultdict(int)
dd['a'] += 1
dd['b'] += 2
print(dd) # defaultdict(<class 'int'>, {'a': 1, 'b': 2})
print(dd['c']) # 0 (자동으로 기본값 0 생성)
# 일반 딕셔너리
d = {}
# print(d['missing']) # KeyError: 'missing'
# defaultdict
dd = defaultdict(int)
print(dd['missing']) # 0