Algorithm

프로그래머스 : 신규 아이디 추천 (72410)

KJihun 2023. 6. 19. 16:28
728x90

문시해알

 

프로그래머스

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

programmers.co.kr

이번 문제는 구현해야 할 부분이 너무 많아 막막했다.

해야 할 양은 많지만 그래도 구현하지 못할 부분은 없는 것 같아 하나하나 천천히 구현해 나갔다.

            // 대문자 -> 소문자로 변환
            String lower = new_id.toLowerCase();
            
            // 소문자, 숫자, 빼기, 점, 언더바만 값 넣기
            String specialCheck = specialCheck(lower);
            
            // 점이 연속해서 두개 이상이라면 하나로 바꾸기
            String decimalCheck = decimalCheck(specialCheck);
            
            // 0번째와 마지막 값이 점이라면 제거하기
            String decimalDelete = decimalDelete(decimalCheck);
            
            // 길이가 0이라면 aaa, 
            // 길이가 3보다 짧다면 while문을 사용하여 길이가 3이 될때까지 마지막 값을 더하기
            // 길이가 16이상이라면 subString을 사용하여 15번째 값까지 자르기
            	//15번째 값이 '.' 이라면 14번째 값 까지 자르기
            answer = lengthCheck(decimalDelete);

이렇게 하나하나 메서드를 구현 후 호출하여 처리하였다.

 

결과는...

실패했다. 테스트 3, 12, 19, 21번에서 실패했다.

프로그래머스는 테스트 코드를 제공해주지 않아 어디서 실패하는지 알기 어려웠다.

그렇기에 한참 동안 코드를 분석하여

'0번째와 마지막 값이 점이라면 제거하기' 부분에서 실패한다는 사실을 알 수 있었다.

 

 

작성한 코드

   public static String decimalDelete(String id){
        String decimalCheck = id;
        if(id.length() != 0) {
            if (id.charAt(0) == '.') {
                decimalCheck = id.substring(1, id.length());

            }
            if (id.charAt(id.length() - 1) == '.') {
                decimalCheck = id.substring(0, id.length() - 1);

            }
        }
        return decimalCheck;
    }

여기서 발생하는건 알겠는데, 어느 구문에서 오류가 발생하는지 가늠이 안 됐기에,

함께 공부하고 있는 동료분들께 코드리뷰를 부탁드렸다.

문제는 '0번째와 마지막 값이 점이라면 제거하기'에 한 개의 점(.)이 들어가게 됐을 때 발생했다.

첫 번째 if문으로 인해 String이 null이 되고, 두 번째 if문에 들어가게 되면서 -1 코드로 인해 예외가 발생했던 것이다.

아래와 같이 코드를 수정했다.

        if((id.length() != 0) && (id.charAt(0) == '.')) {
                decimalCheck = id.substring(1, id.length());
            }
        if ((id.length() != 0) && (id.charAt(id.length() - 1)) == '.')) {
                decimalCheck = id.substring(0, id.length() - 1);

무사히 출력이 됐다! 그리고 다른 동료분께서는 Replace를 사용하면 쉽게 구현할 수 있다고 알려주셨기에 찾아봤다.

Replace는 문자열의 일부를 다른 문자열로 대체하는 작업을 수행해야 할 때

특정 문자열을 찾아 지정된 다른 문자열로 대체할 수 있게 해주는 메서드였다.

 

 

찾아본 후, 조금씩 코드를 수정해 나갔다.

최종코드

class Solution {
    public String solution(String new_id) {
        String answer = new_id.toLowerCase();

		// ^ = not연산자
        // -_., a ~ z, 0 ~ 9의 값이 아니라면 공백("")으로 변환
        answer = answer.replaceAll("[^-_.a-z0-9]","");
        
        // 점이 2개 이상 이라면 하나만 출력
        answer = answer.replaceAll("[.]{2,}",".");
        
        // ^ = 문자열의 시작을 나타냄
        // | = or 연산자
        // $ = 문자열의 끝을 나타냄
        // 시작과 끝의 점을 공백("")으로 변환
        answer = answer.replaceAll("^[.]|[.]$","");
        
        // 공백이라면 a 추가
        if(answer.equals(""))
            answer+="a";
            
        // 16글자가 넘는다면 0 ~ 15까지 slicing
        // 자른 후, 마지막 글자가 .이라면 공백("")으로 변환
        if(answer.length() >=16){
            answer = answer.substring(0,15);
            answer=answer.replaceAll("[.]$","");
        }
        
        //길이가 세글자 이하라면, 세글자가 될 때 까지 마지막 문자열 ++;
        if(answer.length()<=2)
            while(answer.length()<3)
                answer += answer.charAt(answer.length()-1);

        return answer;
    }
}

코드는 간결해지고 가독성이 훨씬 좋아져 만족스러운 결과물이 됐다.

Replace를 사용하며 헷갈렸던 점은 ^(CIRCUMFLEX)가 두 가지의 뜻으로 사용되어서 조금 헷갈렸다.

대괄호 안에 작성하면 부정 연산자, 대괄호 밖에 선언 시 문자열의 시작을 의미했기 때문이다.

 

 

혼자 해결했다면 얼마나 걸릴지 장담 못할 문제였지만, 동료분 덕분에 빨리 문제를 해결하게 되면서

코드리뷰의 이점을 몸소 알게 되었고, 

이 문제 덕분에 replace란 어떤 것인지, 어떤 상황에 사용하며 어떻게 해야 효율적으로 사용할 수 있는지 알 수 있었다.