1. 문제
파일명은 크게 HEAD, NUMBER, TAIL의 세 부분으로 구성된다.
HEAD는 숫자가 아닌 문자로 이루어져 있으며, 최소한 한 글자 이상이다.
NUMBER는 한 글자에서 최대 다섯 글자 사이의 연속된 숫자로 이루어져 있으며, 앞쪽에 0이 올 수 있다. 0부터 99999 사이의 숫자로, 00000이나 0101 등도 가능하다.
TAIL은 그 나머지 부분으로, 여기에는 숫자가 다시 나타날 수도 있으며, 아무 글자도 없을 수 있다.
파일명을 세 부분으로 나눈 후, 다음 기준에 따라 파일명을 정렬한다.
파일명은 우선 HEAD 부분을 기준으로 사전 순으로 정렬한다. 이때, 문자열 비교 시 대소문자 구분을 하지 않는다. MUZI와 muzi, MuZi는 정렬 시에 같은 순서로 취급된다.
파일명의 HEAD 부분이 대소문자 차이 외에는 같을 경우, NUMBER의 숫자 순으로 정렬한다. 9 < 10 < 0011 < 012 < 13 < 014 순으로 정렬된다. 숫자 앞의 0은 무시되며, 012와 12는 정렬 시에 같은 같은 값으로 처리된다.
두 파일의 HEAD 부분과, NUMBER의 숫자도 같을 경우, 원래 입력에 주어진 순서를 유지한다. MUZI01.zip과 muzi1.png가 입력으로 들어오면, 정렬 후에도 입력 시 주어진 두 파일의 순서가 바뀌어서는 안 된다.
무지를 도와 파일명 정렬 프로그램을 구현하라.
2. 풀이
File 클래스
HEAD, NUMBER, 원본파일명을 저장할 클래스를 만든다.
원본파일명이 이미 있기 때문에 head에는 모두 대문자로 변환한 결과를 저장한다.
class File {
int idx;
String head;
int num;
String filename;
File(int idx, String head, String number, String filename){
this.idx = idx;
this.head = head.toUpperCase();
this.num = Integer.parseInt(number);
this.filename = filename;
}
}
파일명 쪼개기
입력받은 위치(i)부터 탐색하되, 첫번째위치와 탐색위치 종류가 다르면 끝낸뒤 그 위치를 반환하는 메서드를 하나 만든다.
첫번째 위치가 숫자인지 저장하고, 하나씩 탐색하면서 종류를 비교하는 방법을 사용했다.
public int split(int i, String filename){
boolean isNum = filename.charAt(i)>='0' && filename.charAt(i) <= '9';
for(;i<filename.length();i++){
if(isNum != (filename.charAt(i)>='0' && filename.charAt(i) <= '9')){
break;
}
}
return i;
}
메인
1. 파일명을 쪼개서 File객체로 만든 뒤 저장한다.
1-1. 임시 String배열을 만들어서, HEAD와 NUMBER을 저장한다.
1-2. 시작 인덱스, 끝 인덱스를 구해서 substring을 사용한다.
1-3. 끝 인덱스를 구하는 것은 위에서 직접 만든 split 메서드를 사용한다.
1-4. 문자열을 저장한 후에는 start에 end를 저장한다.
2. File 배열을 정렬한다. 정렬순서는 1) HEAD 2) NUMBER 3) 인덱스순서 로 한다.
3. String배열을 하나 만들어서 File배열의 원본파일명을 뽑아 저장한뒤, 반환한다.
public String[] solution(String[] files) {
//쪼개서 저장
File[] filelist = new File[files.length];
for(int i=0;i<files.length;i++){
String[] tmp = new String[2];
int start = 0, end;
for(int j=0;j<2;j++){
end = split(start,files[i]);
tmp[j] = files[i].substring(start, end);
start = end;
}
filelist[i] = new File(i,tmp[0], tmp[1], files[i]);
}
//정렬
Arrays.sort(filelist, (o1,o2)-> {
if(!o1.head.toUpperCase().equals(o2.head.toUpperCase())){
return o1.head.compareTo(o2.head);
//return o1.head.compareToIgnoreCase(o2.head);
}else if(o1.num != o2.num){
return o1.num - o2.num;
}else{
return o1.idx - o2.idx;
}
});
//답 저장
String[] answer = new String[files.length];
int i=0;
for(File file:filelist){
answer[i++] = file.filename;
}
return answer;
}
전체 코드
import java.util.*;
class 파일명정렬 {
public String[] solution(String[] files) {
//쪼개서 저장
File[] filelist = new File[files.length];
for(int i=0;i<files.length;i++){
String[] tmp = new String[2];
int start = 0, end;
for(int j=0;j<2;j++){
end = split(start,files[i]);
tmp[j] = files[i].substring(start, end);
start = end;
}
filelist[i] = new File(i,tmp[0], tmp[1], files[i]);
}
//정렬
Arrays.sort(filelist, (o1,o2)-> {
if(!o1.head.toUpperCase().equals(o2.head.toUpperCase())){
return o1.head.compareTo(o2.head);
//return o1.head.compareToIgnoreCase(o2.head);
}else if(o1.num != o2.num){
return o1.num - o2.num;
}else{
return o1.idx - o2.idx;
}
});
//답 저장
String[] answer = new String[files.length];
int i=0;
for(File file:filelist){
answer[i++] = file.filename;
}
return answer;
}
public int split(int i, String filename){
boolean isNum = filename.charAt(i)>='0' && filename.charAt(i) <= '9';
for(;i<filename.length();i++){
if(isNum != (filename.charAt(i)>='0' && filename.charAt(i) <= '9')){
break;
}
}
return i;
}
class File {
int idx;
String head;
int num;
String filename;
File(int idx, String head, String number, String filename){
this.idx = idx;
this.head = head.toUpperCase();
this.num = Integer.parseInt(number);
this.filename = filename;
}
}
}
3. 결과
'코딩테스트 > PROGRAMMERS' 카테고리의 다른 글
[PROGRAMMERS] 수식 최대화 - JAVA (1) | 2023.10.10 |
---|---|
[PROGRAMMERS] 압축 - JAVA (0) | 2023.10.01 |
[PROGRAMMERS] 키패드 누르기 - JAVA (0) | 2023.09.03 |
[PROGRAMMERS] 튜플 - JAVA (0) | 2023.08.04 |
[PROGRAMMERS] 점프와 순간 이동 - JAVA (0) | 2023.08.03 |
댓글