본문 바로가기

코딩 테스트/백준

[Python] 백준 1431 시리얼 번호

 

문제 분석

  • 각 기타는 시리얼 번호가 있다.
  • 모든 시리얼 번호는 알파벳 대문자 + 숫자 조합
  • 정렬 우선순위
    1. 길이가 다르면 짧은 것
    2. 길이가 같으면 모든 자리 중 숫자의 합을 비교해서 작은 합을 가지는 것이 먼저 온다.
    3. 사전순 (알파벳 - 숫자)

 

코드 설계

  • 우선순위가 낮은거 부터 정렬해야 최종적으로는 높은 우선순위가 적용된 채로 정렬되려나?
  1. 길이에 대하여 정렬
  2. 길이가 같은 경우에만 각 시리얼 숫자에 대해 숫자 - 알파벳 분리
    1. 길이가 같은 숫자들을 찾아서
    2. 각 값 하나씩에 대해 A123 -> (123, A)으로 분리 / (숫자, 알파벳)
    3. 숫자의 합에 대하여 정렬

 

정답 코드

빡구현..

import sys
input = sys.stdin.readline

n = int(input())
serial = [input().strip() for _ in range(n)]
nums = [str(i) for i in range(0,10)]
ans = []

# 알파벳 / 숫자 분리
def sep(astr) :
    alp = ''
    num = []
    for s in astr:
        if s in nums:
            num.append(int(s))
        else:
            alp += s
    if len(num) == 0 :
        return int(0)
    return sum(num)

# 3. 먼저 사전 순으로 정렬해두기
serial = sorted(serial)

# 1. 길이에 대하여 정렬
serial = sorted(serial,key = lambda x : len(x))

# 2. 같은 길이가 있는지 확인 -> 숫자의 합 오름차순
length = []
# 2-1. 길이들 체크
for s in serial :
    length.append(len(s))
    
# 2-2. 각 길이들의 갯수(key)에 대한 value 설정
len_dic = {}
len_set = sorted(list(set(length)))
for l in len_set :
    len_dic[l] = []
for s in serial :
    len_dic[len(s)].append(s)
    
# 2-3. 만약 특정 딕셔너리에 value의 개수가 1이 아니면 각 숫자들의 합을 기준으로 정렬
for l in len_set :
    if len(len_dic[l]) > 1 :
        len_dic[l] = sorted(len_dic[l], key=lambda x : sep(x))
        ans += len_dic[l]
    else :
        ans += len_dic[l]

print('\n'.join(ans))

 

다른 사람 코드 1
https://hongcoding.tistory.com/61

(1) sort 이용

n = int(input())

def sum_num(inputs):
    result = 0
    for i in inputs:
        if i.isdigit():
            result+=int(i)
    return result

arr = []
for i in range(n):
    a = input()
    arr.append(a)

arr.sort(key = lambda x:(len(x), sum_num(x), x))
for i in arr:
    print(i)

 

(2) 직접 각 조건의 sort 구현

n = int(input())

arr = []
for i in range(n):
    a = input()
    arr.append(a)


for i in range(n-1):
    for j in range(i+1, n):
        # 짧은 것이 먼저
        if len(arr[i]) > len(arr[j]):
            arr[i], arr[j] = arr[j], arr[i]

        elif len(arr[i]) == len(arr[j]):
            suma=0
            sumb=0
            for x,y in zip(arr[i],arr[j]):
                if x.isdigit():
                    suma+=int(x)
                if y.isdigit():
                    sumb+=int(y)
            if suma > sumb:
                arr[i],arr[j] = arr[j], arr[i]

            elif suma == sumb:
                for x,y in zip(arr[i], arr[j]):
                    if x > y:
                        arr[i],arr[j] = arr[j], arr[i]
                        break
                    elif x < y:
                        break

for i in arr:
    print(i)

 

다른 사람 코드 2
https://dinae.tistory.com/117

n = int(input())
data = []
datasum = dict()
for i in range(n):
    a = input()
    temp = 0
    data.append(a)
    for c in a:
        if c in "123456789":
            temp += int(c)
    datasum[a] = temp

data.sort(key = lambda x : (len(x), datasum[x], x))
for i in data:
    print(i)

datasum리스트에 각 단어의 숫자합을 넣고, 위 3가지 정렬 조건을 sort함수의 key인자에 람다함수를 넣어 정렬하였다.
람다 → len(x)는 x의 길이, datasum[x]는 x번째의 단어의 숫자합, x는 사전순으로 정렬하라는 의미이며, 이를 나열하는 것으로 문제를 해결할 수 있다. 

 

다른 사람 코드 3
https://my-coding-notes.tistory.com/452

주어진 시리얼 코드들을 조건에 맞게 정렬하는 문제이다.
이 문제를 쉽게 풀이하기 위해서 Lambda식을 이용한 정렬법을 숙지해야 한다.

sort 함수에는 key 파라미터를 통해 정렬의 기준이 되는 값을 지정해줄 수 있다.
여기서, lambda식을 이용하면 한 번에 여러 개의 값을 지정해줄 수 있다.

사용법은 아래와 같다.

arr.sort(key = lambda x : (정렬기준1, 정렬기준2, 정렬기준3, …))

import sys
input = sys.stdin.readline

guitar = []
for _ in range(int(input())):
    s = input().rstrip()
    
    # 자리수의 합
    summ = 0
    for i in s:
        if i.isdigit():
            summ += int(i)
    guitar.append((s,summ))
    
guitar.sort(key=lambda x:(len(x[0]),x[1],x[0]))

for i in guitar:
    print(i[0])