문제 설명
- 문자열 파싱과 정렬을 이용하는 문제
- input 가능한 것 : 영문 대소문자, 숫자, 공백(" "), 마침표("."), 빼기 부호("-")
- split_points : [inf, inf]의 형태로 파일명 하나마다 사용
- split_points 배열의 각각 0번째는 head의 끝 지점
- 1번째는 number의 끝지점
- parsing_file_names : 정렬에 필요한 정보를 튜플의 형태로 담는 배열
파싱 기준
- HEAD : 숫자가 아닌 문자로 이루어져 있으며, 최소한 한 글자 이상
- NUMBER : 한 글자에서 최대 다섯 글자 사이의 연속된 숫자로 이루어져 있으며, 앞쪽에 0이 올 수 있다. 0부터 99999 사이의 숫자로, 00000이나 0101 가능
- TAIL : 그 나머지 부분으로, 여기에는 숫자가 다시 나타날 수도 있으며, 아무 글자도 없을 수 있음
정렬 기준
- 파일명은 우선 HEAD 부분을 기준으로 사전 순으로 정렬. 이때, 문자열 비교 시 대소문자 구분을 하지 않음
- 정렬을 위해 head 부분의 문자열을 비교하기 위해서는 동일하게 대문자로나 소문자 한가지로 일치시켜야 함
- 파일명의 HEAD 부분이 대소문자 차이 외에는 같을 경우, NUMBER의 숫자 순으로 정렬한다. 9 < 10 < 0011 < 012 < 13 < 014 순으로 정렬된다. 숫자 앞의 0은 무시되며, 012와 12는 정렬 시에 같은 같은 값으로 처리된다.
- NUMBER에 들어있는 문자열을 숫자로 바꿔주는 작업 필요
- 두 파일의 HEAD 부분과, NUMBER의 숫자도 같을 경우, 원래 입력에 주어진 순서를 유지한다.
- 원본 배열의 입력 순서가 사용되기 때문에 원본 배열은 유지하고 다른 배열들을 이용해서 문제를 해결
겪은 문제
def solution(files):
answer = []
inf = 1001
split_points = [[inf] * 2 for _ in range(len(files))]
upper_files = []
for i in range(len(files)):
file = files[i]
upper_files.append(file.upper())
for j in range(len(file) - 1):
if not file[j].isdigit() and file[j + 1].isdigit():
split_points[i][0] = j
elif file[j].isdigit() and not file[j + 1].isdigit():
split_points[i][1] = j
if split_points[i][1] == inf:
split_points[i][1] = len(files[i]) - 1
paresing_file_names = []
for idx, split_here in enumerate(split_points):
temp = upper_files[idx]
head = temp[:split_here[0] + 1]
number = int(temp[split_here[0] + 1:split_here[1] + 1])
paresing_file_names.append([head, number, idx])
sorted_results = sorted(paresing_file_names, key=lambda x: (x[0], x[1], x[2]))
for result in sorted_results:
answer.append(files[result[2]])
- 위 코드의 결과는 3,4,5,12,13,19,20의 테스트 케이스에서 실패하는 결과를 보았고 알고리즘 상에서 터질 부분은 없다고 생각하여 문제를 다시 확인함
- NUMBER를 파싱하는 과정에서
한 글자에서 최대 다섯 글자 사이의 연속된 숫자
이부분을 간과한 것 같아 해당 부분을 수정함