이번엔 신규 아이디 추천이라는 문제입니다.
이번 문제는 2021 KAKAO BLIND 채용에서 나왔던 문제라고 합니다.
문제가 너무 길어 링크로 대체할게요.
https://school.programmers.co.kr/learn/courses/30/lessons/72410
1단계 newid의 모든 대문자를 대응되는 소문자로 치환합니다.
2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(), 마침표(.)를 제외한 모든 문자를 제거합니다.
3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
5단계 new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다.
6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.
입력 받은 아이디를 해당 단계들을 거치게 하여 아이디를 예상값에 맞추는 문제입니다.
하나의 예시로는
...!@BaT#*..y.abcdefghijklm 라는 아이디를 입력받으면 위 단계를 거쳐 bat.y.abcdefghi로 알맞게 변환해야하는 문제입니다.
import java.util.*;
class Solution {
public String solution(String new_id) {
StringBuilder sb = new StringBuilder();
String lowerCase = new_id.toLowerCase();
for (int i = 0; i < lowerCase.length(); i++) {
char ch = lowerCase.charAt(i);
if (Character.isLetterOrDigit(ch) || ch == '-' || ch == '_' || ch == '.') {
sb.append(ch);
}
}
String temp = sb.toString().replaceAll("\\.{2,}", ".");
sb.setLength(0);
sb.append(temp);
removeDot( sb);
if(sb.length() == 0){
sb.append("a");
}
removeDot( sb);
if (sb.length() > 15) {
sb.setLength(15);
}
removeDot( sb);
while(sb.length() <3){
sb.append(sb.charAt(sb.length() -1 ));
}
return sb.toString();
}
private static boolean contains(char[] array, char value) {
for (char c : array) {
if (c == value) {
return true;
}
}
return false;
}
private void removeDot(StringBuilder sb){
if(sb.length() > 0 && sb.toString().startsWith(".") || sb.toString().endsWith(".")){
if (sb.toString().startsWith(".")) {
sb.deleteCharAt(0);
}
if (sb.length() > 0 && sb.toString().endsWith(".")) {
sb.deleteCharAt(sb.length() - 1);
}
}
}
}
문자열을 가공하기에 StringBuilder를 사용하는게 맞아 사용하려 했는데 문제는 해당 과정에서 StringBuilder의 메서드를 잘 몰라 검색을 하긴 했습니다.
그리고 처음 풀이에서는
String temp = sb.toString().replaceAll("\\.{2,}", ".");
여기를 보시면 "\\.{2,}"이게 있는데 이를 정규표현식이라 합니다.
정규 표현식이란 문자열의 패턴을 정의하고 해당 패턴에 일치하는 문자열을 표현하는 일종의 형식이 있는 언어이면 java.util.regex 패키지에 포함되어 있습니다.
"\\.{2,}"이거는 .을 이스케이프 문자 \\로 한다음 {2,}에서는 이전 것들까지 2번이상 반복할 경우의 문자열 부분을 가져옵니다. 그다음 replaceAll()메서드를 통하여 .이 연속되는 부분들을 모두 .하나로만 변경하여 해결합니다.
처음엔 그냥 for문 로직으로 하였으나 자꾸 제출할 때 정답률 89%에서 멈춰서 테스트코드에 예시를 이것저것 넣으면서 해도 잘 되는데 뭐가 문제일까 하다가 질문 게시판에 보니까 정규표현식이 있길래 찾아봐서 해결하였습니다.
정규표현식도 리눅스 같은 CLI환경에서는 알면 텍스트 변환 및 검색에 유용하다하여 나중에 한번 공부해두려고 합니다.
특수문자 걸러내는 것도 정규표현식으로 하면 "[^a-zA-Z0-9]"로 하면 알파벳 대소문자랑 숫자들이 아닌 것들을 나타내는데 이를 사용해도 괜찮으나 혹시몰라 중복 . 통합부분을 먼저 해봤는데 되길래 특수문자 검열 부분은 일단 건드리지는 않았습니다.
이상입니다.