코딩 테스트 연습/백준 silver

[백준] S4. 등수 구하기 (Python)

카누가 좋아요 2023. 6. 18. 18:31

❓ 문제

https://www.acmicpc.net/problem/1205

 

1205번: 등수 구하기

첫째 줄에 N, 태수의 새로운 점수, 그리고 P가 주어진다. P는 10보다 크거나 같고, 50보다 작거나 같은 정수, N은 0보다 크거나 같고, P보다 작거나 같은 정수이다. 그리고 모든 점수는 2,000,000,000보

www.acmicpc.net

 

 

 

💡 해결하기

1️⃣

우선 케이스 분류를 해야 하는 문제이다.

* p: 랭킹 리스트에 올라갈 수 있는 점수의 개수

 

0. n이 0일 경우

➡️ 점수 리스트가 비어 있으면 새로운 점수는 무조건 리스트에 추가 가능할 뿐만 아니라 본인 하나밖에 없어 항상 1등이 되므로 1을 출력하고 종료

 

1. 주어진 점수 리스트(랭킹 리스트)의 길이가 p보다 작을 경우

➡️ 새로운 점수는 무조건 리스트에 추가가 가능하므로 추가

 

2. 주어진 점수 리스트(랭킹 리스트)의 길이가 p와 같을 경우

    2-1. 점수 리스트에서 가장 작은 점수보다 새로운 점수보다 더 크거나 같을 경우

    ➡️ 새 점수가 리스트에 올라갈 수 없으므로 -1 출력하고 종료

    2-2. 새로운 점수가 점수 리스트에서 가장 작은 점수보다 더 큰 경우

    ➡️ 점수 리스트에서 가장 작은 점수 하나를 제거하고 새 점수를 추가한다.

 

2️⃣

위에서 종료되지 않은 경우는 등수를 따로 구해야 하는 경우이다.

우선, 등수를 구하기 위해 새로운 점수가 추가된 리스트를 내림차순 정렬해 준 후 등수를 구한다.

아래와 같은 방식으로 진행한다.

➡️ 첫번째 점수일 경우 무조건 1등

➡️ 뒤로 1칸씩 갈수록 기본적으로 등수 하나씩 낮아짐. (등수 숫자 자체는 증가)

➡️ 동일한 점수가 있다면 그 점수들은 등수가 같음.

➡️ 동일한 점수가 나오다가 다른 점수가 나오면 바로 앞에서 동일한 점수가 나온 만큼 등수가 더 낮아져야 함.

 

위 과정 진행 중 점수 리스트에서 새로운 점수와 똑같은 점수가 나올 시 그 등수를 출력하고 종료하면 된다.

 

 

 

💻 Python으로 코드 작성하기

 

n, new_score, p = map(int, input().split())     # 리스트에 있는 점수의 개수, 새로운 점수, 리스트에 올라갈 수 있는 점수의 개수

if n == 0:     # 리스트에 있는 점수의 개수가 없다면
    print(1)     # 새로운 점수는 무조건 1등이 되므로
    exit()     # 프로그램 종료

scores = list(map(int, input().split()))     # 이미 존재하는 점수 리스트
scores.sort(reverse=True)     # 점수 오름차순 정렬

def get_grade(scores, new_score):     # 등수를 구하는 함수
    scores.append(new_score)     # 새로운 점수는 무조건 리스트에 올라갈 수 있다.
    scores.sort(reverse=True)     # 점수 리스트 다시 내림차순 정렬 
    cnt = 1     # 동일한 점수가 나오는 횟수 (본인 포함)
    grade = 0     # 등수
    for i in range(len(scores)):
        if i == 0:     # 첫번째 점수는 무조건 1등
            grade += cnt
        else:     # 첫번째 점수가 아닐 경우 이전 점수를 살펴보아야 함.
            if scores[i] == scores[i-1]:     # 이전 점수와 동일할 경우 
                cnt += 1     # 등수는 그대로, cnt만 증가
            else:
                grade += cnt     # 지금까지 누적된 동일한 점수가 나오는 횟수만큼 등수가 내려감.
                cnt = 1     # cnt는 다시 1로 초기화
        if scores[i] == new_score:     # 현재 점수가 새로운 점수와 같다면 
            print(grade)     # 새로운 점수의 등수를 출력하고
            return      # 함수 종료

if len(scores) < p:     # 이미 존재하는 점수의 수가 리스트에 올라갈 수 있는 점수의 개수보다 작으면
    get_grade(scores, new_score)     # 등수 구하는 함수 실행
else:     # 점수 리스트가 꽉 차있다면
    if scores[-1] >= new_score:     # 점수 리스트에서 가장 작은 점수보다 현재 점수가 더 작거나 같다면 
        print(-1)     # 새로운 점수가 리스트에 올라가는 것이 불가능하므로 -1 출력 후 끝
    else:     # 그렇지 않을 경우
        scores.pop()     # 가장 작은 점수 제거
        get_grade(scores, new_score)     # 등수 구하는 함수 실행

 

 

 

🙂 돌아보기

등수를 구하는 함수를 작성하는 과정에서 동일한 점수가 나오다가 다른 점수가 나왔을 때의 등수를 구할 때 동일한 점수가 나온 횟수를 초기화해주지 않아서 문제가 발생했었다.

백준에서 등수를 구하는 코드를 이전에도 몇 번 작성했었는데 틀린 것을 보니 실수를 조심해야겠다.