코딩테스트/PROGRAMMERS

[PROGRAMMERS] 파일명 정렬 - JAVA

5월._. 2023. 11. 19.
728x90

1. 문제

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

파일명은 크게 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. 결과

댓글