복's
[ Programmers - LV2 ] [3차] 파일명 정렬 본문
https://school.programmers.co.kr/learn/courses/30/lessons/17686
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
단순히 주어진 조건으로 파일명을 정렬하는 문제이다.
나는 주로 정렬 문제는 구현 되어있는 sort() 사용하거나 필요에 따라서 인터페이스 Compartor 를 구현 해서 풀이 햐였는데 오늘은 뭔가 색다른 풀이를 원하고 있었고, 조금 더 객체지향(?)적인 코드를 짜고 싶어졌다.
결국 과하다는 생각에 코드를 조금 되돌리기는 했지만 이번 풀이 덕분에 조금은 틀에서 벗어난 기분을 느껴서 좋았다.
📌 분석
- 파일 구성: HEADER - BODY(NUM) - TAIL
- 정렬 조건:
- HEADER(1차): 대소문자 관계 없이 문자열 비교
- BODY(2차): 숫자 크기 비교
- 위 조건을 생각하면 TAIL 은 정렬에 관여하지 않는다.
그 밖에 문자열 값에 대한 조그마한 조건들이 있지만 크게 신경쓰지 않아도 문제는 풀린다.
📌 최종 코드 - Java
결국 정렬 문제기 때문에 중요한 부분은 정렬 코드다.
조건 1은 Header 기준으로 비교하고, 두 Header 가 똑같다면 뒤의 Body(num) 으로 비교해야 한다.
작은 조건중 하나는 모든게 같다면 입력 값 순서를 유지하는 Stable Sort 를 요구 했는데, 처음에는 for 을 통해서 인덱스를 받아서 sequnce 를 따로 저장해서 유지 하려고 했지만 신경쓸 필요 없었다.
@Override
public int compareTo(File file) {
int headRes = this.head.compareTo(file.head);
if(headRes == 0) {
return this.num - file.num;
}
return headRes;
}
최종 코드는 아래와 같다.
import java.util.ArrayList;
import java.util.List;
class Solution {
public String[] solution(String[] files) {
List<File> fileList = new ArrayList<>();
for(String file : files) {
fileList.add(getFile(file));
}
fileList.sort(File::compareTo); // 정의 해놓은 compareTo 기준으로 정렬
return fileList.stream().map(File::getOrigin).toArray(String[]::new); // 파일의 원본 이름 기준으로 배열 생성
}
public File getFile(String file) {
int idx = 0; // file 맨 앞 글자
String head;
int num;
StringBuilder sb = new StringBuilder();
// HEAD 추출
while(idx < file.length() && !Character.isDigit(file.charAt(idx))) {
sb.append(file.charAt(idx++));
}
head = sb.toString();
sb.setLength(0); // StringBuilder 초기화
// NUM 추출
while(idx < file.length() && Character.isDigit(file.charAt(idx))) {
sb.append(file.charAt(idx++));
}
num = Integer.parseInt(sb.toString());
sb.setLength(0);
return new File(file, head, num);
}
class File implements Comparable<File> {
String origin;
String head;
int num;
public File(String origin, String head, int num) {
this.origin = origin;
this.head = head.toUpperCase();
this.num = num;
}
@Override
public int compareTo(File file) {
int headRes = this.head.compareTo(file.head);
if(headRes == 0) {
return this.num - file.num;
}
return headRes;
}
public String getOrigin() {
return origin;
}
}
}
📌 결과
📌 마치며...
객체지향적인 코드라고 했던건 위 코드가 아닌 처음 제출한 코드인데 구조 자체가 완전히 달랐다.
아래와 같이 파일을 구성하는 각 요소들에 대한 인스턴스를 갖고 있는데, 코드를 결국 수정한 이유는 알고리즘 문제 풀이에 적합하지 않았다고 생각이 되어서...
매 파일 생성마다 4개의 인스턴스를 생성해서 갖고 있어야 했고, 각 요소(내부 클래스) 의 역할을 나눈만큼 큰 기능이 없었다.
- HEADER
FILE - BODY(NUM)
- TAIL
매번 클래스와 그에 상응하는 메타 데이터 생성이 (물론 성능에 큰 영향은 없음) 알고리즘 문제 풀이라는 목적에 부합하지 않다고 생각하였다.
하지만 이렇게 풀어도 될까 라는 마음을 갖고 풀어서 그런지 재밋게 문제 풀이를 할 수 있었다.
'알고리즘 > Programmers' 카테고리의 다른 글
[ Programmers - LV2 ] 쿼드압축 후 개수 세기 (3) | 2024.09.08 |
---|---|
[ Programmers - LV2 ] 광물 캐기 (1) | 2024.09.01 |
[ Programmers - LV2 ] 과제 진행하기 (1) | 2024.08.23 |
[ Programmers - LV2 ] [PCCP 기출문제] 2번 / 석유 시추 (0) | 2024.08.17 |
[ Programmers - LV3 ] 거스름돈 (1) | 2023.12.31 |