코딩 테스트

(Java) 프로그래머스 - 파일명 정렬

로승리 2022. 9. 4. 02:37

문제 이름은 파일명 정렬이지만 정렬보다 문자열을 분리하는데 더 고민을 많이 했던 것 같다.

요구 조건도 간단하게 처리할 수 있는 정도여서 어려운 문제는 아니었던 것 같다.

 

로직은 문자열을 head - number -tail 부분으로 분리해서 File 인스턴스를 생성해 리스트에 넣고 정렬하면 된다.

문자열 분리는 처음에 split으로 시도했으나 regex를 [0-9]으로 설정하면 기준 문자가 포함되지 않아서 실패했고

StringTokenizer를 사용하면 기준 문자는 포함할 수 있지만 delim을 1~99999까지 만들 수가 없어서 실패했다.

어쩔 수 없이 number 부분이 시작되는 인덱스와 끝나는 인덱스를 찾아 subString으로 나누어서 처리했다.

이 부분의 로직이 if문이 중첩되어 있는 부분인데 너무 길고 눈에 잘 들어오지 않기 때문에 리펙터링이 필요할 것 같다.

문제에 tail 부분이 없을수도 있다고 했으므로 문자열 분리가 끝났는데도 end가 0이면 tail이 없다는 의미임으로 length() - 1 값을 넣어주었다.

 

문자열 분리가 끝났으면 List <File>에 인스턴스를 생성해 삽입하고 Comparator를 이용해 정렬한다.

 

여기서 생각해야 할 문제의 요구 조건은

1. head 부분에서 대소문자를 구별하지 않는다고 했으므로 문자열을 toLowerCase()를 이용해서 반환한다.

2. 9 < 10 < 0011 < 012 < 13 < 014 순으로 처럼 앞자리의 0은 무시된다고 했으므로 parseInt를 이용해서 반환하면 자연스럽게 앞자리의 0은 사라진다.

 

그렇게 정렬이 끝나면 File 클래스의 getStr을 이용해서 answer 배열에 삽입하면 된다.


최종 코드

import java.util.*;
class Solution {
    public String[] solution(String[] files) {
        String[] answer = new String[files.length];

        // File 객체를 담을 list 생성
        List<File> list = new ArrayList<>();

        // subString으로 문자열 나누기
        for (int i = 0; i < files.length; i++) {
            String temp = files[i];
            // number 부분이 시작되었는지 판단하는 변수
            boolean flag = false;
            // number 부분의 시작과 끝 인덱스 변수, number 부분의 길이 변수
            int start = 0;
            int end = 0;
            int cnt = 0;
            for (int j = 0; j < temp.length(); j++) {
                // number 문자가 나오지 않았다는것
                if(!flag) {
                    if(Character.isDigit(temp.charAt(j))) {
                        flag = true;
                        start = j;
                        cnt++;
                    }
                    // number 문자가 시작 되었으면
                } else {
                    if(cnt != 5) {
                        // 숫자라면
                        if(Character.isDigit(temp.charAt(j))) {
                            cnt++;
                            // number 부분이 끝났다는 것
                        } else {
                            end = j - 1;
                            break;
                        }
                    } else {
                        end = j - 1;
                        break;
                    }
                }
            }
            // end가 0이면 tail이 없다는 의미
            if(end == 0) {
                end = temp.length() - 1;
            }

            // FIle 리스트에 값 삽입
            list.add(new File(temp.substring(0, start), temp.substring(start, end + 1), temp.substring(end + 1) ,""));
        }

        // 1순위 - head값을 오름차순, 2순위 number의 값을 오름차순으로 정렬
        list.sort(Comparator.comparing(File::getHead).thenComparing(File::getNumber));

        // list에서 str을 answer 배열에 삽입
        for (int i = 0; i < list.size(); i++) {
            answer[i] = list.get(i).getStr();
        }
        return answer;
    }
    // File 클래스
    static class File {
        String head;
        String number;
        String tail;
        String str;

        // 생성자
        File(String head, String number, String tail, String str) {
            this.head = head;
            this.number = number;
            this.tail = tail;
            this.str = str;
        }

        // String을 만들어 반환하는 메서드
        public String getStr() {
            str = head + number + tail;
            return str;
        }
        // head를 소문자로 바꾸어 반환하는 메서드
        public String getHead() {
            return head.toLowerCase();
        }
        // number를 Integer로 바꾸어 반환하는 메서드
        public int getNumber() {
            return Integer.parseInt(number);
        }
    }
}