본문 바로가기
[Python] Programmers/Level1

[프로그래머스/Level1] 복서 정렬하기 (위클리 챌린지 6주차)

by 파크영 2021. 9. 6.

문제 설명

복서 선수들의 몸무게 weights와, 복서 선수들의 전적을 나타내는 head2head가 매개변수로 주어집니다. 복서 선수들의 번호를 다음과 같은 순서로 정렬한 후 return 하도록 solution 함수를 완성해주세요.

  1. 전체 승률이 높은 복서의 번호가 앞쪽으로 갑니다. 아직 다른 복서랑 붙어본 적이 없는 복서의 승률은 0%로 취급합니다.
  2. 승률이 동일한 복서의 번호들 중에서는 자신보다 몸무게가 무거운 복서를 이긴 횟수가 많은 복서의 번호가 앞쪽으로 갑니다.
  3. 자신보다 무거운 복서를 이긴 횟수까지 동일한 복서의 번호들 중에서는 자기 몸무게가 무거운 복서의 번호가 앞쪽으로 갑니다.
  4. 자기 몸무게까지 동일한 복서의 번호들 중에서는 작은 번호가 앞쪽으로 갑니다.

제한사항

  • weights의 길이는 2 이상 1,000 이하입니다.
    • weights의 모든 값은 45 이상 150 이하의 정수입니다.
    • weights[i] 는 i+1번 복서의 몸무게(kg)를 의미합니다.

 

  • head2head의 길이는 weights의 길이와 같습니다.
    • head2head의 모든 문자열은 길이가 weights의 길이와 동일하며, 'N', 'W', 'L'로 이루어진 문자열입니다.
    • head2head[i] 는 i+1번 복서의 전적을 의미하며, head2head[i][j]는 i+1번 복서와 j+1번 복서의 매치 결과를 의미합니다.
      • 'N' (None)은 두 복서가 아직 붙어본 적이 없음을 의미합니다.
      • 'W' (Win)는 i+1번 복서가 j+1번 복서를 이겼음을 의미합니다.
      • 'L' (Lose)는 i+1번 복사가 j+1번 복서에게 졌음을 의미합니다.
    • 임의의 i에 대해서 head2head[i][i] 는 항상 'N'입니다. 자기 자신과 싸울 수는 없기 때문입니다.
    • 임의의 i, j에 대해서 head2head[i][j] = 'W' 이면, head2head[j][i] = 'L'입니다.
    • 임의의 i, j에 대해서 head2head[i][j] = 'L' 이면, head2head[j][i] = 'W'입니다.
    • 임의의 i, j에 대해서 head2head[i][j] = 'N' 이면, head2head[j][i] = 'N'입니다.

입출력 예

weights head2head result
[50,82,75,120] ["NLWL","WNLL","LWNW","WWLN"] [3,4,1,2]
[145,92,86] ["NLW","WNL","LWN"] [2,3,1]
[60,70,60] ["NNN","NNN","NNN"] [2,1,3]

 

입출력 예 설명을 보시려면 더보기를 누르세요

더보기

입출력 예 설명

 

입출력 예 #1

  • 다음은 선수들의 정보를 나타낸 표입니다.
선수 번호 vs 1번 vs 2번 vs 3번 vs 4번 승률 자기보다 무거운 복서를 이긴 횟수 몸무게
1번 - 패배 승리 패배 33.33% 1회 50kg
2번 승리 - 패배 패배 33.33% 0회 82kg
3번 패배 승리 - 승리 66.66% 2회 75kg
4번 승리 승리 패배 - 66.66% 0회 120kg
  • 본문에 서술된 우선순위를 따라 [3,4,1,2] 를 return 합니다.

 

입출력 예 #2

  • 다음은 선수들의 정보를 나타낸 표입니다.
선수 번호 vs 1번 vs 2번 vs 3번 승률 자기보다 무거운 복서를 이긴 횟수 몸무게
1번 - 패배 승리 50% 0회 145kg
2번 승리 - 패배 50% 1회 92kg
3번 패배 승리 - 50% 1회 86kg
  • 본문에 서술된 우선순위를 따라 [2,3,1] 을 return 합니다.

 

입출력 예 #3

  • 다음은 선수들의 정보를 나타낸 표입니다.
선수 번호 vs 1번 vs 2번 vs 3번 승률 자기보다 무거운 복서를 이긴 횟수 몸무게
1번 - - - 0% (무전적) 0회 60kg
2번 - - - 0% (무전적) 0회 70kg
3번 - - - 0% (무전적) 0회 60kg
  • 본문에 서술된 우선순위를 따라 [2,1,3] 을 return 합니다.

 


나의 풀이

 

[Python(파이썬)]

def solution(weights, head2head):
    answer = []
    for i in range(len(head2head)):
        n = 0
        for j in range(len(head2head[i])):
            if head2head[i][j] == 'W' and weights[i] < weights[j]:  # 무거운 복서를 이긴 횟수
                    n += 1  
        # 다른 복서랑 붙어본 적 없는 경우 승률 0
        winning_rate = 0 if len(head2head[i].replace('N','')) == 0 else head2head[i].count('W') / len(head2head[i].replace('N', ''))
        # 0: 승률, 1: 무거운 복서를 이긴 횟수, 2: 자신의 몸무게, 3: 복서 번호
        answer.append([winning_rate, n, weights[i], i+1])
    # 0-3번까지 순서대로 정렬하기 (-x[] : 역순으로 정렬)
    answer = sorted(answer, key=lambda x: (-x[0], -x[1], -x[2], x[3]))
    return [answer[i][3] for i in range(len(answer))]

 

 


학습한 내용

※ 풀기 전 체크할 내용
- 다른 복서랑 붙어본 적이 없는 복서의 승률 = 0%
- 'N' (None) = 두 복서가 아직 붙어본 적이 없음
- 'W' (Win) = 이김
- 'L' (Lose) = 졌음

<우선순위>
- 전체 승률이 높은 복서의 번호가 앞
- 승률이 동일한 복서의 번호들 중에서는 자신보다 몸무게가 무거운 복서를 이긴 횟수가 많은 복서의 번호가 앞
- 무거운 복서를 이긴 횟수까지 동일한 복서의 번호들 중에서는 자기 몸무게가 무거운 복서의 번호가 앞
- 자기 몸무게까지 동일한 복서의 번호들 중에서는 작은 번호가 앞

 

풀이 과정
1. 이차원 리스트 만들기
1-1 승률 구하기
1-2 자신보다 몸무게가 무거운 복서를 이긴 횟수 구하기
2. 이차원 리스트 정렬하기

 

1. 이차원 리스트 만들기

 

정렬을 쉽게 하기 위해서 복서들의 정보를 이차원 리스트로 만들었다.

# 0: 승률, 1: 무거운 복서를 이긴 횟수, 2: 자신의 몸무게, 3: 복서 번호
[[0.3333333333333333, 1, 50, 1], # 1번 선수
 [0.3333333333333333, 0, 82, 2], # 2번 선수
 [0.6666666666666666, 2, 75, 3], # 3번 선수
 [0.6666666666666666, 0, 120, 4]] # 4번 선수

 

for i in range(len(head2head)):
        n = 0
        for j in range(len(head2head[i])):
            if head2head[i][j] == 'W' and weights[i] < weights[j]:  # 무거운 복서를 이긴 횟수
                    n += 1  
        # 다른 복서랑 붙어본 적 없는 경우 승률 0
        winning_rate = 0 if len(head2head[i].replace('N','')) == 0 else head2head[i].count('W') / len(head2head[i].replace('N', ''))
        # 0: 승률, 1: 무거운 복서를 이긴 횟수, 2: 자신의 몸무게, 3: 복서 번호
        answer.append([winning_rate, n, weights[i], i+1])

 

 

1-1 승률 구하기

 

 head2head[i].count('W') / len(head2head[i].replace('N', ''))

 

1) i 복서가 한 경기 횟수 구하기 ('N(붙어 본 적 없음)' 제거 후 길이)

2) i 복서가 이긴 횟수 /  i 복서가 한 경기 횟수

 

ex) 'NLWL'인 경우

1) len('NLWL'.replace('N', '')) -> 'LWL' 길이 -> 3

2) 'NLWL'.count('W') -> 1

3) 1/3 = 0.33333333...

 

 

<ZeroDivisionError: division by zero 주의>

'N'만 있다면(다른 복서랑 붙어본 적 없다면) 0이 나오기 때문에 예외 처리해줘야 한다. 

 

 

  • count() - 리스트의 특정 원소 개수 구하는 함수
 

[Python(파이썬)] 리스트의 특정 원소 개수 구하기, Counter

리스트의 특정 원소 개수 구하기 count() - 리스트의 특정 원소 개수 구하는 함수 >>> test = [1, 3, 5, 2, 1, 3, 6, 8] >>> test.count(1) 2 >>> test.count(8) 1 >>> test = ['abc', 'apple', 'abaegd', 'abcdea..

young-library.tistory.com

 

 


1-2 자신보다 몸무게가 무거운 복서를 이긴 횟수 구하기

 

if head2head[i][j] == 'W' and weights[i] < weights[j]:  # 무거운 복서를 이긴 횟수
	n += 1

 

1. head2head[i][j] == 'W' -> 이겼는지 확인

2. 이겼다면 weights[i] < weights[j] -> 내 몸무게보다 상대방의 몸무게가 많은지 확인

3. 두 가지 모두 만족했다면 n += 1

 

 


2. 이차원 리스트 정렬하기

 

문제에서 정해준 우선순위대로 정렬해야 한다. 

 

<우선순위>

- 전체 승률이 높은 복서의 번호가 앞
-> 인덱스 0번
- 승률이 동일한 복서의 번호들 중에서는 자신보다 몸무게가 무거운 복서를 이긴 횟수가 많은 복서의 번호가 앞
-> 인덱스 1번
- 무거운 복서를 이긴 횟수까지 동일한 복서의 번호들 중에서는 자기 몸무게가 무거운 복서의 번호가 앞
-> 인덱스 2번
- 자기 몸무게까지 동일한 복서의 번호들 중에서는 작은 번호가 앞
-> 인덱스 3번

 

# 정렬 전
# 0: 승률, 1: 무거운 복서를 이긴 횟수, 2: 자신의 몸무게, 3: 복서 번호
[[0.3333333333333333, 1, 50, 1], 
 [0.3333333333333333, 0, 82, 2], 
 [0.6666666666666666, 2, 75, 3], 
 [0.6666666666666666, 0, 120, 4]]

# 정렬 후 
[[0.6666666666666666, 2, 75, 3], 
 [0.6666666666666666, 0, 120, 4], 
 [0.3333333333333333, 1, 50, 1],
 [0.3333333333333333, 0, 82, 2]]

 

answer = sorted(answer, key=lambda x: (-x[0], -x[1], -x[2], x[3]))

 

0번 인덱스에 대해 역순으로 먼저 정렬 후 1번 인덱스에 대해 역순으로 정렬하고 그다음 2번 인덱스에 대해 역순으로 정렬 후 3번 인덱스에 대해 정렬

 

  • 2차원 리스트 정렬하는 방법
 

[Python(파이썬)] 2차원 리스트 정렬

1차원 리스트 정렬 [Python(파이썬)] sort와 sorted 차이 sort와 sorted차이 sort() .sort(key = , reverse = True|False) - 리스트를 정렬해주는 기능을 하는 함수, 반환값이 None이다. - 정렬된 값을 리턴하지..

young-library.tistory.com

 

 


문제 출처

 

코딩테스트 연습 - 6주차

복서 선수들의 몸무게 weights와, 복서 선수들의 전적을 나타내는 head2head가 매개변수로 주어집니다. 복서 선수들의 번호를 다음과 같은 순서로 정렬한 후 return 하도록 solution 함수를 완성해주세요

programmers.co.kr

 

댓글