[java] 프로그래머스 - 파일명 정렬

3 분 소요

업데이트:

문제

프로그래머스-파일명 정렬
입력받은 파일 이름을 기준에 따라 정렬하여 출력하는 문제.

파일명은 HEAD, NUMBER, TAIL로 세 부분으로 나눈다
HEAD : 문자로 이루어져있고, 한 글자 이상이다
NUMBER : 한 글자에서 최대 5글자 사이의 연속된 숫자다 (앞에 0이 오는 숫자도 가능)
TAIL : HEAD, NUMBER를 제외한 나머지 부분으로, 아무 글자가 없을 수 있다

  • 제한 사항
    입력받는 파일들의 목록 files는 1000개 이하의 문자열 배열이다
    각 파일명은 100글자 이하 길이로, 숫자를 하나이상 포함하고 있는 영문자로 시작하는 문자열이다
    중복된 파일명은 없으나, 대소문자, 숫자 앞부분의 0 차이가 있는 경우는 주어질 수 있다

  • 예시
    입력: [img12.png, img10.png, img02.png, img1.png, IMG01.GIF, img2.JPG]
    출력: [img1.png, IMG01.GIF, img02.png, img2.JPG, img10.png, img12.png]

주어진 head가 img로 동일하므로, 숫자의 크기에 따라 정렬한다
head와 number가 같은 경우, 입력받은 순서의 우선대로 정렬한다

풀이

역시나 문제를 꼼꼼히 읽어야함을 느끼는 계기..(ㅠㅠ)
우선 HEAD, NUMBER로 구분하는 것은 쉽지만 내가 오답이 나왔던 이유는 크게 2가지가 있다

  1. HEAD 비교 -> NUMBER 비교 -> TAIL 비교 인줄암
    NUMBER까지 같으면 들어온 순서대로 라는 조건을 눈에서 스킵해버림
  2. NUMBER는 한 글자에서 최대 5글자사이의 연속된 숫자다
    맘대로 숫자라면 전부 NUMBER에 해버림 ㅋㅎ
    예를들어 “IMG12345678.PNG” 라면 IMG / 12345 / 678.PNG 로 구분해야한다

입력받은 파일명을 HEAD, NUMBER, TAIL로 쪼개 객체를만든다
파일명을 toCharArray()를 이용해서 한 글자씩 보면서 숫자인지 판별한다
숫자인지 판별할때는 c[i]-'0'을 써서 0과 같거나 크고, 9보다 작거나 같으면 숫자다!
첫 숫자가 나오면 인덱스를 저장했다가, 같은 방법으로 숫자가 아닐때의 두번째 인덱스를 찾는다

두 인덱스의 길이가 5보다 크면 5로 맞춰준다
0 ~ 첫 인덱스(첫 숫자가 나온 인덱스) === subString ===> HEAD
첫 인덱스 ~ 두번째 인덱스 === subString ===> NUMBER
두번째 인덱스 ~ 마지막 === subString ===> TAIL

다 같은경우 입력받은 순서가 필요하므로 idx도 같이 저장해서 객체를 만든다

생성한 객체를 ArrayList에 저장한 다음, 기준에 따라 정렬한다
HEAD 비교 -> NUMBER 비교 -> 인덱스 비교

소스코드

import java.util.*;
class Solution {
 public String[] solution(String[] files) {
		ArrayList<File> f = new ArrayList<>();
	// 메서드 만들어서 객체 만들어 ~~~ HEAD / NUMBER / TAIL / IDX
		for (int i = 0; i < files.length; i++) {
			f.add(createFileObject(files[i], i));
		}
	// 정렬해 ~~
		f.sort(new Comparator<File>() {
			@Override
			public int compare(File o1, File o2) {
				if (o1.headLower.equals(o2.headLower)) {
					if (Integer.parseInt(o1.num) == Integer.parseInt(o2.num)) {
						return o1.idx - o2.idx;
					} else {
						return Integer.parseInt(o1.num) - Integer.parseInt(o2.num);
					}
				} else {
					return o1.headLower.compareTo(o2.headLower);
				}
			}
		});

		String[] answer = new String[f.size()];
		for (int i = 0; i < f.size(); i++) {
			answer[i] = f.get(i).toString();
		}
		return answer;
	}

	// 파일을 쪼개서 객체로 만들자 ~
	private File createFileObject(String string, int i) {
		char c[] = string.toCharArray();
		int s1 = 0;
		int s2 = string.length() - 1;
		// 숫자 첫 인덱스
		for (int j = 0; j < c.length; j++) {
			if (c[j] - '0' >= 0 && c[j] - '0' < 10) {
				s1 = j;
				break;
			}
		}
		// 숫자 끝 인덱스(숫자미포함)
		for (int j = s1 + 1; j < c.length; j++) {
			if (c[j] - '0' < 0 || c[j] - '0' > 9) {
				s2 = j;
				break;
			}
		}
		// subString(a, b)라면 b는 포함안되므로 1추가
		if(s2==string.length()-1)
			s2++;
		// 5글자 넘게 차이나? 5글자까지 잘라~
		if (s2 - s1 > 5) {
			s2 = s1 + 5;
		}

		String head = string.substring(0, s1);
		String num = null;
		String tail = null;
		// tail이 없는 경우, number만 넣어주고 tail은 null 유지
		if (s1 == s2) {
			num = string.substring(s1, s1 + 1);
		} else {
			// 둘다 있어 ~ 둘다 만들어 ~
			num = string.substring(s1, s2);
			tail = string.substring(s2);
		}
		return new File(head, num, tail, i);
	}
}

class File {
	String head;
	String headLower;
	String num;
	String tail;
	int idx;
	public File(String head, String num, String tail, int idx) {
		super();
		this.head = head;
		this.headLower = head.toLowerCase();
		this.num = num;
		this.tail = tail;
		this.idx = idx;
	}
	@Override
	public String toString() {
		return head + num + tail;
	}
}

댓글남기기