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

1 분 소요

문제

출처

이해

입력

  • 파일명 배열 files
    • 크기: [0, 1000]
    • 원소
      • 형식: 문자열
      • 크기: [2, 100]

출력

  • 규칙에 맞게 정렬된 파일명 배열

규칙

  1. 파일명
    • 영문자로 시작한다.
    • 하나 이상의 숫자를 포함한다.
    • HEAD, NUMBER, TAIL 세 부분으로 나눌 수 있다.
  2. HEAD는 파일명 앞부분의 숫자가 아닌 문자열이다.
    • 한 글자 이상이다.
  3. NUMBER는 HEAD 뒷부분의 숫자인 문자열이다.
    • 1 ~ 5글자이며 앞에 0이 올 수 있다.
  4. TAIL은 NUMBER 이후의 모든 문자열이다.
    • 비어있을 수 있다.
  5. 정렬 기준
    1. HEAD에 대하여 대소문자 구분 없이 사전 순 정렬한다.
    2. 1번으로 결정되지 않을 경우, 문자열인 NUMBER를 로 생각했을 때 오름차순 정렬한다.
      • 앞부분의 '0'을 제거하면 된다.
      • 다시 말해 001, 01, 1은 모두 같은 값으로 취급한다.
    3. 1, 2번으로 결정되지 않을 경우 주어진 순서를 유지한다.

예시

정렬

파일명 HEAD NUMBER TAIL
foo9.txt foo 9 .txt
foo010bar020.zip foo 010 bar020.zip
F-15 F- 15 (빈 문자열)

입출력

입력: 
["img12.png", "img10.png", "img02.png", "img1.png", "IMG01.GIF", "img2.JPG"]

출력: 
["img1.png", "IMG01.GIF", "img02.png", "img2.JPG", "img10.png", "img12.png"]

접근

이 문제는 복잡한 규칙을 얼마나 정확히 구현하는지 확인하는 문제이다. 그런데 파이썬은 문자열을 다루는 아주 강력한 방법(regular expression, formatted string literal)을 지원하기 때문에 이를 십분 활용하면 구현 없이 쉽고 빠르게 문제를 해결할 수 있다.

구현

import re

def solution(files):
    answer = []

    # 정규표현식 라이브러리로 문자열을 HEAD, NUMBER, TAIL로 쪼개는 패턴을 만든다.
    # group1 (HEAD): 1개 이상의 숫자가 아닌 문자열 (\D+)
    # group2 (NUMBER): 1~5개의 숫자인 문자열 (\d{1,5})
    # group3 (TAIL): 나머지 문자열 (.*)
    pattern = re.compile('(\D+)(\d{1,5})(.*)')

    for file in files:
        # 파일명에 패턴을 적용하여 쪼갠다
        matched = pattern.match(file)

        # HEAD의 대소문자 구분을 없앤다.
        head = matched.group(1).lower()

        # NUMBER의 길이를 5자리로 맞춘다.
        # 0>5 의미: 
        # 주어진 문자열을 우측 정렬 후, 5칸 미달인 경우 빈 칸은 0으로 채운다.
        # "12" -> "00012"
        number = f'{matched.group(2):0>5}'

        answer.append([file, head, number])

    # HEAD로 정렬하고, 동일한 경우 NUMBER로 정렬한다.
    # python의 sort는 stable sort이기 때문에 처음 주어진 입력 순서를 보장한다.
    answer.sort(key=lambda x: (x[1], x[2]))

    return [x[0] for x in answer]

댓글남기기