문제
민겸이는 2023 INPC 참가자들의 점수를 관리하는 업무를 맡고 있다. 대회가 종료되면 순위표를 공개하려 하는데,
이를 만들기 위해 필요한 데이터는 참가자의 이름, 점수, 비공개 여부 3가지이다.
다음은 순위표를 만드는 방법에 대한 자세한 설명이다.
2023 INPC의 참가자는 N명이다.
각 참가자는 이름, 점수, 비공개 여부 3가지 값을 각자 가지고 있다.
이름은 영어 소문자 알파벳으로 구성된 길이 1 이상 10 이하의 문자열이다.
점수는 1 이상 109이하의 정수이다.
비공개 여부는 자신을 순위표에서 숨길지 공개할지 결정하는 참 또는 거짓의 값이다.
두 참가자의 점수가 다르다면 더 높은 점수를 받은 참가자에게 더 높은 순위를 매긴다.
가능한 가장 높은 순위는 1등이고, 가장 낮은 순위는 N등이다.
동점자가 있다면 모두에게 가능한 높은 순위를 매긴다.
예를 들어 6인의 참가자의 점수가 각각 10, 10, 8, 6, 6, 6이라면, 순위는 순서대로 1, 1, 3, 4, 4, 4가 된다.
순위표는 공개를 선택한 참가자들 중 순위가 높은 참가자부터 순위, 이름, 점수를 보여주어야 한다.
순위가 같다면 이름이 사전순으로 앞서는 참가자를 먼저 보여주어야 한다.
비공개를 선택한 참가자를 보여주면 안된다.
비공개 여부는 실제 순위에 영향을 주지 않는다.
민겸이는 순위표 작성 프로그램을 만드는 즐거움을 INPC 참가자들에게도 공유하고 싶어 이 문제를 만들었다. 여러분도 위 설명에 따라 순위표 작성 프로그램을 만들어보자.
입력
첫 번째 줄에 참가자의 수 N이 주어진다.
두 번째 줄부터 N개의 줄에 걸쳐 하나의 줄 당 하나의 참가자의 정보가 주어진다. 한 참가자의 정보는 '{'로 시작하여 '}'로 끝나며, {"name":"이름","score":점수,"isHidden":비공개 여부}의 형식으로 공백 없이 주어진다. 비공개 여부는 참인 경우 1, 거짓인 경우 0으로 주어진다.
첫 번째 참가자의 정보 바로 앞에는 여는 대괄호가 하나, 마지막 참가자의 정보 바로 뒤에는 닫는 대괄호가 하나 존재한다. 또한 각 참가자의 정보 사이에는 줄이 끝날 때마다 쉼표가 하나씩 존재한다.
출력
올바른 순위표를 출력한다.
각 줄에는 한 참가자의 순위, 이름, 점수를 공백으로 구분하여 출력한다. 순위가 높은 참가자를 먼저 출력하고, 순위가 같은 참가자가 있다면 이름이 사전순으로 앞서는 참가자를 먼저 출력한다. 비공개 여부가 참인 사용자는 출력하지 말아야 함에 유의한다.
제한
1 ≤ N ≤ 1,000
모든 사람의 이름은 서로 다르다.
점수를 공개하는 참가자가 적어도 한 명 존재한다.
문제풀이
이번 문제는 문자열을 파싱해서 주어진 기준으로 정렬하는 문제였다. 되게 간단하다.
문자열은 Json 형식과 같이 주어진다.
이 문자열을 split하고 나눠서 필요한 정보만 파싱할 수 있다.
하지만 본인은 해당 과정을 모두 스킵했다.
주어진 문자열을 파싱해서 불러올 수 있으나, 파이썬에서는 ast라는 라이브러리가 존재한다.
해당 라이브러리를 이용하면, 문자열로 된 리스트나 dictionary를 타입에 맞게 변환해줄 수 있다.
예를 들어서 "[1, 2, 3]" 과 같은 문자열이 있으면,
이것을 파이썬 리스트 타입으로 변환이 가능한 것이다.
따라서 입력으로 들어오는 모든 문자열을 받아서 변환해서 정렬을 수행했다.
문제는, 동점자 처리였다.
동점자 처리는 간단하다. 주어진 순위에서 동점인 경우, 높은 등수로 이를 배치하고, 그 길이만큼 순위를 늘려주면 된다.
이를 위해서, 이전 점수와 현재까지 계산된 동점자 수를 정리하였고,
지금 입력되어야 할 순위를 함께 변수로 저장했다.
이를 기반으로 정렬하여 출력해주면 쉽게 해결할 수 있다.
본인은 문제를 제대로 읽지 못해서, 계속 틀렸는데
이걸 보시는 분들도 쉽게 생각하셨으나, 틀리시는 경우에는 문제를 다시 읽어보셔도 좋을 것 같다.
"isHidden이 1인 경우에, 순위표에 포함은 시키되, 출력만 하지 않는 것"
위 조건을 순위표에서 아예 제거하는 것이라고 착각해서 문제를 계속 틀렸었다.
문제를 더 자세히 읽어줘야 겠다..
정답코드
import ast
# 참가자 수 읽기
n = int(input().strip())
# 참가자 정보 읽기
members = ""
for _ in range(n):
members += input().strip()
participants = ast.literal_eval(members)
# 점수 내림차순, 이름 사전순으로 정렬
participants.sort(key=lambda x: (-x['score'], x['name']))
# 순위 계산
ranking = []
current_rank = 1
previous_score = None
same_rank_count = 0
for i, participant in enumerate(participants):
name, score, is_hidden = participant['name'], participant['score'], participant['isHidden']
if score == previous_score:
# 동점자 처리: 이전 순위를 유지하고 카운트 증가
same_rank_count += 1
else:
# 새로운 점수: 현재 순위에 동점자 수를 더해 갱신
current_rank += same_rank_count
same_rank_count = 1
ranking.append((current_rank, name, score, is_hidden))
previous_score = score
# 결과 출력 (isHidden == 0인 참가자만 출력)
for rank, name, score, is_hidden in ranking:
if is_hidden == 0:
print(rank, name, score)
'CodingTest > BOJ' 카테고리의 다른 글
10828 백준 스택 - 파이썬 (1) | 2024.12.11 |
---|---|
백준 1550 16진수 - Python (0) | 2024.12.09 |
백준 1260 DFS와 BFS - Python (0) | 2024.12.05 |
백준 1213번 팰린드롬 만들기 - Python (0) | 2024.12.04 |
백준 1182 부분수열의 합 - Python (0) | 2024.11.28 |