[프로그래머스] 파일명 정렬 - python 본문

코테 문제 풀이

[프로그래머스] 파일명 정렬 - python

미니모아 2022. 4. 21. 15:57
반응형

파일명 정렬

문제

소스 파일 저장소에 저장된 파일명은 100 글자 이내로, 영문 대소문자, 숫자, 공백(" "), 마침표("."), 빼기 부호("-")만으로 이루어져 있다. 파일명은 영문자로 시작하며, 숫자를 하나 이상 포함하고 있다.

파일명은 크게 HEAD, NUMBER, TAIL의 세 부분으로 구성된다.

  • HEAD는 숫자가 아닌 문자로 이루어져 있으며, 최소한 한 글자 이상이다.
  • NUMBER는 한 글자에서 최대 다섯 글자 사이의 연속된 숫자로 이루어져 있으며, 앞쪽에 0이 올 수 있다. 0부터 99999 사이의 숫자로, 00000이나 0101 등도 가능하다.
  • TAIL은 그 나머지 부분으로, 여기에는 숫자가 다시 나타날 수도 있으며, 아무 글자도 없을 수 있다.

파일명을 세 부분으로 나눈 후, 다음 기준에 따라 파일명을 정렬한다.

  • 파일명은 우선 HEAD 부분을 기준으로 사전 순으로 정렬한다. 이때, 문자열 비교 시 대소문자 구분을 하지 않는다. MUZImuzi, MuZi는 정렬 시에 같은 순서로 취급된다.
  • 파일명의 HEAD 부분이 대소문자 차이 외에는 같을 경우, NUMBER의 숫자 순으로 정렬한다. 9 < 10 < 0011 < 012 < 13 < 014 순으로 정렬된다. 숫자 앞의 0은 무시되며, 012와 12는 정렬 시에 같은 같은 값으로 처리된다.
  • 두 파일의 HEAD 부분과, NUMBER의 숫자도 같을 경우, 원래 입력에 주어진 순서를 유지한다. MUZI01.zipmuzi1.png가 입력으로 들어오면, 정렬 후에도 입력 시 주어진 두 파일의 순서가 바뀌어서는 안 된다.

무지를 도와 파일명 정렬 프로그램을 구현하라.

제한사항

  • 입력으로 배열 files가 주어진다.
    • files는 1000 개 이하의 파일명을 포함하는 문자열 배열이다.
    • 각 파일명은 100 글자 이하 길이로, 영문 대소문자, 숫자, 공백(" "), 마침표("."), 빼기 부호("-")만으로 이루어져 있다. 파일명은 영문자로 시작하며, 숫자를 하나 이상 포함하고 있다.
    • 중복된 파일명은 없으나, 대소문자나 숫자 앞부분의 0 차이가 있는 경우는 함께 주어질 수 있다. (muzi1.txt, MUZI1.txt, muzi001.txt, muzi1.TXT는 함께 입력으로 주어질 수 있다.)

풀이

일단 header number tail로 나눠야한다.

나눌 때 인덱스도 같이 넣고

Header 정렬 : 소문자로 통일

Number: int 로

Tail : 나머지

각 3부분을 나눠서 튜플로 저장한 후에 조건에 맞춰서 정렬해주면 된다.

처음에는 정규식을 이용해서 나눴었는데 tail이 없거나 구분 없이 바로 숫자가 올 경우 number부분을 5글자만 추출할 방법을 못찾았다.

그래서 그냥 한글자씩 영문인지 숫자인지 비교해서 분류하는 방식으로 풀었다.

def solution(files):
    answer = []
    for i, file in enumerate(files):
        header = []
        numbers = []
        tail = []
        for j, char in enumerate(file):
            if not char.isdigit() and not numbers:
                header.append(char)
            elif char.isdigit() and len(numbers) < 5:
                numbers.append(char)
            else:
                tail.append(file[j:])
                break
        files[i] = (''.join(header), ''.join(numbers), ''.join(tail), i)  
    files.sort(key=lambda x:(x[0].lower(), int(x[1]), x[3]))
    return [''.join(x[:-1]) for x in files]

다른 사람 풀이

굳이 분류하지 않고 바로 조건에 맞는 부분을 찾아서 해당 부분을 키로 정렬할 수 있었다.

하위 조건을 먼저 정렬한 후에 상위 조건으로 정렬한다.

import re
​
def solution(files):
    a = sorted(files, key=lambda file : int(re.findall('\d{1,5}', file)[0]))
    b = sorted(a, key=lambda file : re.split('\d+', file.lower())[0])
    return b

다른 사람 풀이2

조건에 매칭되는 문자열을 찾아서 나누려면 이렇게 하면 된다. match로 해당 하는 값을 찾아서 groups()를 사용해 각 조건에 맞는 문자열들을 묶어서 튜플로 만들어준다.

header: 영문소문자 1개 이상

number: 숫자 5개 이하

tail : 아무 문자나 0개 이상

import re

def solution(files):

    def key_function(fn):
        head,number,tail = re.match(r'([a-z-. ]+)(\d{,5})(.*)',fn).groups()
        return [head,int(number)]

    return sorted(files, key = lambda x: key_function(x.lower()))

 

반응형
Comments