[SWEA] 1983 조교의 성적 매기기

[SWEA] 1983 조교의 성적 매기기

문제 링크

이 문제는 모든 학생들의 성적을 줄 세우고, 특정 학생의 성적을 반환할 수 있어야 한다. 모든 학생들에게 제한된 수의 각 학점을 부여하기 위해서 수식을 작성할수도 있겠지만, 직관적으로 부여할 수 있는 모든 학점을 list로 작성하여 학생의 성적 순서에 따라서 A+부터 D0까지의 학점을 부여할 수 있도록 작성해보았다.

모든 학생들에게 성적을 부여하는 것이 아닌, 순위로부터 성적을 매길 수 있는 방법을 택한다면 메모리 측면에서 더 효율적일 수 있겠다.

나의 풀이

# 테스트케이스 수
t = int(input())

# 각 테스트 케이스의 값은 answer에 저장
answer = []

for _ in range(t):
    n, k = map(int, input().split())
    max = n // 10 # 부여할 수 있는 grade별 갯수

		# 낮은 등급부터 grades 배열에 모두 저장
    grades=[]
    for i in range(10):
        for j in range(max):
            grades.append('D0')
        for j in range(max):
            grades.append('C-')
        for j in range(max):
            grades.append('C0')
        for j in range(max):
            grades.append('C+')
        for j in range(max):
            grades.append('B-')
        for j in range(max):
            grades.append('B0')
        for j in range(max):            
            grades.append('B+')
        for j in range(max):
            grades.append('A-')
        for j in range(max):
            grades.append('A0')
        for j in range(max):
            grades.append('A+')

		# 학생별 점수 배열을 students 저장
    students = [list(map(int, input().split())) for _ in range(n)]

		# 학생별 환산 점수와 학생 번호를 순서쌍으로 scores에 저장
    scores = []

    for i in range(n):
        scores.append((students[i][0]*0.35+students[i][1]*0.45+students[i][2]*0.2, i+1))

    scores.sort(reverse=True) #환산 점수를 기준으로 내림차순 정렬 (순서쌍 첫 번째가 기준값임, 같을 시 두 번째 값 비교)

		# 정렬된 scores 배열을 순회하면서 테스트케이스의 학생 번호와 일치하는 값이 나오면 answer에 grade를 삽입하고 반복문 종료
    for i in range(n):
        if scores[i][1] == k:
            answer.append(grades.pop())
						break
        else:
            grades.pop()

for i in range(t):
  print(f"#{i+1} {answer[i]}")

2022.05.26 다시 풀이

for tc in range(1, int(input())+1):
    n, k = map(int, input().split()) # n = 총 학생 수, k = 점수 알고 싶은 학생 번호

    student = list(range(0,n+1))
    score = [0]
    grade = ['D0', 'C-', 'C0', 'C+', 'B-', 'B0', 'B+', 'A-', 'A0', 'A+']

    k_rank = 0

    for i in range(n):
        mid, fin, assi = map(int, input().split())
        score.append(mid*0.35 + fin * 0.45 + assi * 0.2)

    _dict = dict(zip(student, score))
    sorted_dict = sorted(_dict.items(), key=lambda item: item[1], reverse=True)

    for i in range(len(sorted_dict)):
        if sorted_dict[i][0] == k:
            k_rank = i+1

    step = n//10

    for i in range(step,n+1,step):
        result = grade.pop()
        if k_rank <= i:
            break

    print(f"#{tc}",result)

저번에 작성한 로직보다는 훨씬 깔끔해진 것 같다.. 특히 모든 grade를 저장했던 부분은 비효율의 끝판왕이었던 것 같다…

이번에는 dictionary를 이용해서 학생들을 줄 세우고 k 번째 학생의 랭킹을 구하고

각 등급에 속할 수 있는 인원수 만큼을 건너 뛰면서 grade를 pop하는데, k 학생의 랭킹이 속한 범위에서 반복문을 멈추고 해당 grade를 출력할 수 있도록 했다.

  • 학생들 총점 구하기
  • 학생 등수 구하기 (1등 부터 시작이기 때문에 Index 조심)
  • 학생이 어떤 구간에 속하는지 파악(n//10) → 학점 출력

좀 더 단순화 하고 싶었는데 이정도에 그쳤다.


딕셔너리 자료형을 sorting할 때 애 먹을 것 같아서 한 번 정리했다.

dict sort

dict = {'0':1, '3':2, '1':3}
print(dict) # {'0': 1, '3': 2, '1': 3}
print(sorted(dict)) # ['0', '1', '3']

dict.items()를 활용해서 정렬하지 않으면 key값으로만 정렬하고 값을 반환함.

Key로 정렬

dict = {'0':1, '3':2, '1':3}
print(dict.items()) # dict_items([('0', 1), ('3', 2), ('1', 3)])
print(sorted(dict.items())) # [('0', 1), ('1', 3), ('3', 2)]

Value로 정렬

오름, 내림 차순은 reverse=True 명시해주면 됨

dict = {'0':1, '3':2, '1':3}
print(sorted(dict.items(), key=lambda item:item[1])) # [('0', 1), ('3', 2), ('1', 3)]

© 2021. All rights reserved.