Algorithm/Programmers
17686. 파일명 정렬
사랑우주인
2025. 3. 25. 22:47
문제
https://school.programmers.co.kr/learn/courses/30/lessons/17686
풀이
import java.util.*;
class Solution {
// File 클래스
class File {
String head;
int number;
int tailIndex;
String origin;
public File(String head, int number, int tailIndex, String origin) {
this.head = head;
this.number = number;
this.tailIndex = tailIndex;
this.origin = origin;
}
public String getHead() { return this.head;}
public int getNumber() { return this.number;}
public int getTailIndex() { return this.tailIndex;}
public String getOrigin() {return this.origin;}
}
public String[] solution(String[] files) {
String [] answer = {};
List<File> fList = new ArrayList<>();
for(int i = 0; i<files.length; i++) {
String f = files[i];
String[] split = splitFile(f);
String head = convertToLowercase(split[0]);
int number = convertToInteger(split[1]);
int tailIndex = i;
String origin = f;
fList.add(new File(head, number, tailIndex, origin));
}
sortFile(fList);
answer = fList.stream()
.map(File::getOrigin)
.toArray(String[]::new);
return answer;
}
// 파일 정렬
List<File> sortFile(List<File> fList) {
Collections.sort(fList, (o1, o2) -> {
if(!o1.getHead().equals(o2.getHead()))
return o1.getHead().compareTo(o2.getHead());
else if(o1.getNumber() != o2.getNumber())
return o1.getNumber() - o2.getNumber();
else
return o1.getTailIndex() - o2.getTailIndex();
});
return fList;
}
//Head, Number, Tail 분리
String[] splitFile(String file) {
int n = file.length();
int i = 0;
int headStart=0;
int numberStart= 0;
while(numberStart < n) {
if(file.charAt(numberStart) > '9' || file.charAt(numberStart) < '0') {
numberStart++;
} else {
break;
}
}
int tailStart = numberStart;
while(tailStart< n) {
if('0' <=file.charAt(tailStart) && file.charAt(tailStart) <= '9') {
tailStart++;
} else {
break;
}
}
String head = file.substring(headStart, numberStart);
String number = file.substring(numberStart, tailStart);
String tail = file.substring(tailStart, n);
return new String[]{head, number, tail};
}
// 소문자 변환
String convertToLowercase(String head) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < head.length(); i++) {
char currentChar = head.charAt(i);
if (Character.isUpperCase(currentChar)) {
result.append(Character.toLowerCase(currentChar));
} else {
result.append(currentChar);
}
}
return result.toString();
}
// 숫자 변환
int convertToInteger(String number) {
int result = 0;
int digit = 1;
int n = number.length();
for(int i = 0 ; i< n; i++) {
result+=digit * (number.charAt(n-1-i) - '0');
digit*=10;
}
return result;
}
}
회고
- 문자열이 Head, Number, Tail로 구성되어 있다.
- Head는 숫자 외 문자로 이루어져있다. 정렬 기준은 문자열이다.
- Number는 숫자인 문자열이다. "0012"도 숫자 취급한다. 정렬 기준은 숫자이다.
- Tail은 Head와 Number도 아닌 숫자 또는 문자가 섞인 문자열이다. 정렬 기준은 생성 순서이다.
파일명은 숫자 또는 문자로 구성된 문자열이면서 Head, Number, Tail 구간으로 분리된다. 정렬 기준이 구간마다 다르기 때문에, 정렬 로직 커스텀이 필요했다.
// 파일 정렬
List<File> sortFile(List<File> fList) {
Collections.sort(fList, (o1, o2) -> {
if(!o1.getHead().equals(o2.getHead()))
return o1.getHead().compareTo(o2.getHead());
else if(o1.getNumber() != o2.getNumber())
return o1.getNumber() - o2.getNumber();
else
return o1.getTailIndex() - o2.getTailIndex();
});
return fList;
}
정렬 로직을 커스텀하기 이전에 비교를 위해 구간을 정렬 기준에 따라 값을 변환시켰다.
- Head -> String 정렬
- Number -> Integer 정렬
- Tail -> 생순 순(Index) 정렬