[Python] - 객체 정렬, 등수 표현, 객체 정렬 문제 풀이 (정보 정렬, 좌표 거리, 정렬된 위치 탐색)

2023. 9. 22. 16:34파이썬(Python)

반응형

1. 객체 정렬 시 등수 표현

- 국어, 수학, 영어 점수를 가진 학생 정보가 주어진다.

- 총합이 높은 순서로 정렬할 때, 1등부터 n 등까지 등수에 해당하는 학생의 번호를 출력한다.

 

- 총합에 따라 내림차순 정렬이 되면서 학생의 번호도 같이 움직인다.

- 정렬 후 등수에 해당하는 번호를 출력한다.

- 객체에 학생 번호에 해당하는 멤버 변수를 추가한다.

- 등수별 학생의 번호를 출력하기 위해 index를 출력하는 enumerate 함수를 사용한다.

- start 값으로 시작 index 값을 설정할 수 있다.

 

Class 이용

class Student:
    def __init__(self, kor, math, eng, num):
        self.kor = kor
        self.math = math
        self.eng = eng
        self.num = num


n = int(input())
student_points = []
for num in range(1, n+1):
    kor, math, eng = map(int, input().split())
    student_points.append(Student(kor, math, eng, num))

student_points.sort(key=lambda x: -(x.kor+x.math+x.eng))

for idx, student in enumerate(student_points, start=1):
    print(f'{idx}등은 총점 {student.kor+student.math+student.eng}인 {student.num}번 학생입니다.')

 

>> 5
>> 60 80 40
>> 30 70 90
>> 80 10 30
>> 40 70 60
>> 50 10 70

1등은 총점 190인 2번 학생입니다.
2등은 총점 180인 1번 학생입니다.
3등은 총점 170인 4번 학생입니다.
4등은 총점 130인 5번 학생입니다.
5등은 총점 120인 3번 학생입니다.

 

Tuple 이용

# 입력값
5
60 80 40
30 70 90
80 10 30
40 70 60
50 10 70
n = int(input())
student_points = [tuple(map(int, input().split())) for _ in range(n)]
student_points = list(enumerate(student_points, start=1))
# student_points = [(1, (60, 80, 40)), (2, (30, 70, 90)), (3, (80, 10, 30)), (4, (40, 70, 60)), (5, (50, 10, 70))]

student_points.sort(key=lambda x: -(x[1][0]+x[1][1]+x[1][2]))
# student_points = [(1, (2, (30, 70, 90))), (2, (1, (60, 80, 40))), (3, (4, (40, 70, 60))), (4, (5, (50, 10, 70))), (5, (3, (80, 10, 30)))]
for idx, (num, (kor, math, eng)) in enumerate(student_points, start=1):
    print(f'{idx}등은 총점이 {kor+math+eng}점인 {num}번 학생입니다.')

 

1등은 총점이 190점인 2번 학생입니다.
2등은 총점이 180점인 1번 학생입니다.
3등은 총점이 170점인 4번 학생입니다.
4등은 총점이 130점인 5번 학생입니다.
5등은 총점이 120점인 3번 학생입니다.

 

Q) 정보 정렬 프로그램

- 정보를 입력할 인원수 n을 입력한다.

- name이라고 입력하면 이름 사전순으로 정렬한다. (대, 소문자 구분)

- height라고 입력하면 키 순으로 정렬한다.

- weight라고 입력하면 몸무게 순으로 정렬한다.

- name, height, weight 말고 다른 단어를 입력하면 please enter again이라는 메시지가 출력 후, 다시 입력한다.

- 순위, 이름, 키, 몸무게 순으로 출력한다.

 

n = int(input())
info = [tuple(input().split()) for _ in range(n)]

while True:
    inp = input()
    if inp == 'name':
        info.sort(key=lambda x: x[0].lower())
        break

    elif inp == 'height':
        info.sort(key=lambda x: -int(x[1]))
        break

    elif inp == 'weight':
        info.sort(key=lambda x: -int(x[2]))
        break

    else:
        print('Please enter again')
        continue

for idx, (name, height, weight) in enumerate(info, start=1):
    print(f'{idx}. {name} {height} {weight}')

 

>> 5
>> Tom 178 70
>> john 184 84
>> Harry 172 74
>> irish 164 52
>> William 188 86
>> name
1. Harry 172 74
2. irish 164 52
3. john 184 84
4. Tom 178 70
5. William 188 86
>> 5
>> Tom 178 70
>> john 184 84
>> Harry 172 74
>> irish 164 52
>> William 188 86
>> height
1. William 188 86
2. john 184 84
3. Tom 178 70
4. Harry 172 74
5. irish 164 52
>> 5
>> Tom 178 70
>> john 184 84
>> Harry 172 74
>> irish 164 52
>> William 188 86
>> weight
1. William 188 86
2. john 184 84
3. Harry 172 74
4. Tom 178 70
5. irish 164 52

 

- 정보는 (이름, 키, 몸무게)처럼 tuple로 이루어져 있다.

- 이름을 정렬할 때 다음과 같이 입력한다.

info.sort(key=lambda x: x[0])

- 결과는 대문자가 먼저 나오고 소문자가 다음으로 나온다.

1. Harry 172 74
2. Tom 178 70
3. William 188 86
4. irish 164 52
5. john 184 84

- 이유는 문자를 정렬하면 ASCII 코드 값에 대응하여 숫자로 판단하기 때문이다.

- 참고로 A는 65번, a는 97번이다.

- 따라서 모든 대문자는 모든 소문자보다 ASCII 코드가 낮으므로 오름차순으로 정렬하면 대문자가 소문자보다 먼저 출력하게 된다.

- 대, 소문자를 포함하여 정렬하기 위해서는 문자를 모두 소문자 (lower()) 또는 대문자 (upper())로 바꾸어 정렬한다.

info.sort(key=lambda x: x[0].lower())
# or
info.sort(key=lambda x: x[0].upper())

- 참고로 사전 역정렬순이면 reverse=True를 추가한다.

info.sort(key=lambda x: x[0].lower(), reverse=True)

- 키, 몸무게를 정렬하기 위해서는 현재 입력한 정보인 tuple 내의 데이터가 모두 string이므로 int로 변환한다.

- 내림차순으로 정렬하기 위해서 -를 붙인다.

- 이러한 과정은 while 루프에서 작용되고 이름, 키, 몸무게를 입력하면 정렬한 뒤 루프를 탈출한다.

- 그 외의 것을 입력하면 다시 입력하라는 메시지가 출력되고 다시 while을 실행한다.

- 순번을 출력하기 위해 enumerate를 사용하여 index를 출력한다.

 

 

Q) 좌표 거리

- 기준이 되는 좌표 x, y를 입력한다.

- 입력할 좌표의 개수 n을 입력한다.

- n개의 좌표 x, y를 입력한다.

- 기준점과 거리가 가까운 순서대로 n개의 좌표를 출력한다.

 

x, y = map(int, input().split())
n = int(input())

points = []
for _ in range(n):
    new_x, new_y = map(int, input().split())
    distance = (((new_x-x)**2)+((new_y-y)**2))**0.5
    points.append((new_x, new_y, distance))

points.sort(key=lambda x: x[2])
for idx, (x, y, _) in enumerate(points, start=1):
    print(f'{idx}. ({x}, {y})')

 

>> 2 5
>> 4
>> -1 5
>> 3 7
>> -4 7
>> 2 3

1. (2, 3)
2. (3, 7)
3. (-1, 5)
4. (-4, 7)

 

- 점과 점 사이의 공식은 다음과 같다.

- 거리가 짧은 순서대로 출력해야 하기 때문에 distance를 기준으로 오름차순으로 정렬한다.

- enumerate를 사용해 index와 좌표값을 출력한다.

 

 

Q) 정렬 후 숫자 위치 탐색

- 임의의 개수의 숫자들을 입력한다.

- 정렬 조건을 입력한다. (asc : 오름차순, des : 내림차순)

- 정렬된 숫자들을 출력하고 정렬 전의 숫자의 index가 정렬 후 몇 번째 index로 이동했는지 출력한다.

- 예) 1번째 숫자 3은 정렬 후 5번째로 이동

- 만약 숫자가 중복되면 오름차순먼저 입력한 숫자가 앞에 온다.

- 반대로 내림차순먼저 입력한 숫자가 뒤에 온다.

 

arr = list(map(int, input().split()))
arr = list(enumerate(arr, start=1))
inp = input()


def sort_print(arr):
    for _, num in arr:
        print(num, end=' ')
    print()
    arr = list(enumerate(arr, start=1))
    arr.sort(key=lambda x: (x[1][0]))

    for curr_idx, (first_idx, num) in arr:
        print(f'{first_idx}번째 숫자 {num}은 정렬 후 {curr_idx}번째로 이동')


if inp == 'asc':
    arr.sort(key=lambda x: (x[1], x[0]))
    print('오름차순으로 정렬하면 다음과 같습니다.')
    sort_print(arr)

elif inp == 'des':
    arr.sort(key=lambda x: (-x[1], -x[0]))
    print('내림차순으로 정렬하면 다음과 같습니다.')
    sort_print(arr)

 

>> 7 6 15 6 20 9 13
>> asc
오름차순으로 정렬하면 다음과 같습니다.
6 6 7 9 13 15 20
1번째 숫자 7은 정렬 후 3번째로 이동
2번째 숫자 6은 정렬 후 1번째로 이동
3번째 숫자 15은 정렬 후 6번째로 이동
4번째 숫자 6은 정렬 후 2번째로 이동
5번째 숫자 20은 정렬 후 7번째로 이동
6번째 숫자 9은 정렬 후 4번째로 이동
7번째 숫자 13은 정렬 후 5번째로 이동
>> 7 6 15 6 20 9 13
>> des
내림차순으로 정렬하면 다음과 같습니다.
20 15 13 9 7 6 6
1번째 숫자 7은 정렬 후 5번째로 이동
2번째 숫자 6은 정렬 후 7번째로 이동
3번째 숫자 15은 정렬 후 2번째로 이동
4번째 숫자 6은 정렬 후 6번째로 이동
5번째 숫자 20은 정렬 후 1번째로 이동
6번째 숫자 9은 정렬 후 4번째로 이동
7번째 숫자 13은 정렬 후 3번째로 이동

 

- 입력한 숫자들의 index를 알기 위해 enumerate를 사용한다.

- 오름차순일 경우 현재 index와 숫자로 이루어진 튜플 데이터에서 숫자를 기준으로 정렬한다.

- 동일한 숫자가 있을 경우 먼저 입력 (index가 낮은)한 기준으로 정렬하기 때문에 index를 두 번째 우선순위로 정한다.

- 내림차순일 경우 동일한 숫자가 있을 때, 나중에 입력 (index가 높은)한 기준으로 정렬한다.

- 오름차순 또는 내림차순으로 정렬한 후, index를 찾기 위해 enumerate를 사용한다.

- 출력을 하기 위해 정렬 전의 index를 기준으로 오름차순으로 정렬한다.