프로그래머스 - 신규 아이디 추천

이동준·2022년 8월 11일
0

2021년 카카오 공채 1번 문제

🎯 Logic

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이 될 때까지 반복해서 끝에 붙입니다.

위 과정에 따라서 코드를 구현하기만 하면 되는 문제이다.
다만, 굵게 강조한 동사를 모아보면 크게 3가지인데 다음과 같다.
1. 제거한다
2. 치환한다
3. 붙인다(대입한다)
나는 자바로 문제를 풀 것이므로 내가 아는 문자열 함수들 중에서 저 기능을 하는 것이 무엇인지 생각해야 했다.
1. 제거한다 -> replace, replaceAll, subString
2. 치환한다 -> replace, replaceAll, subString
3. 붙인다 -> +

위 함수를 적절히 사용하면 되는데 특히 replaceAll 함수를 사용하기 위해서는 정규식을 자유자재로 쓸 줄 알아야 했다

첫 번째 풀이

public String solution(String new_id) {
        // 1단계
        new_id = new_id.toLowerCase();
        // 2단계
        String s;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < new_id.length(); i++) {
            char c = new_id.charAt(i);
            if (isLowerCase(c) || isNumber(c) || c == '-' || c == '_' || c == '.') sb.append(c);
        }
        s = sb.toString();
        // 3단계
        s= s.replaceAll("[.]{2,}", ".");
        // 4단계
        if(s.charAt(0)=='.' && s.charAt(s.length()-1)=='.') {
            if(s.length()==1) s = "";
            else s = s.substring(1, s.length() - 1);
        }
        else if(s.charAt(0)=='.') s = s.substring(1, s.length());
        else if(s.charAt(s.length()-1)=='.') s = s.substring(0, s.length() - 1);
        // 5단계
        if(s.length()==0) s += "a";
        // 6단계
        if(s.length() >=16) s = s.substring(0,15);
        if(s.charAt(s.length()-1)=='.') s = s.substring(0, s.length() - 1);
        // 7단계
        char lastChar = s.charAt(s.length() - 1);
        if(s.length()<=2){
            while(s.length()<3)
                s += lastChar;
        }
        return s;
    }
    public static boolean isLowerCase(char c) {
        if(c>=97 && c<=122) return true;
        else return false;
    }

    public static boolean isNumber(char c) {
        if(c>=48 && c<=57) return true;
        else return false;
    }

(이 문제를 풀 때 3단계에서 정규식을 몰라서 상당히 해맸었다)
제거하는 과정을 subString에만 의존하다 보니 길이가 1에 대한 예외 상황도 생기고 풀고도 그다지 좋은 풀이가 아닌 것 같았다.

두 번째 풀이

public String solution(String new_id) {
        // 1단계
        String s= new_id.toLowerCase();
        // 2단계
        s = s.replaceAll("[^-_.a-z0-9]", "");
        // 3단계
        s = s.replaceAll("[.]{2,}", ".");
        // 4단계
        s = s.replaceAll("^[.]|[.]$", "");
        // 5단계
        if(s.isEmpty()) s += "a";
        // 6단계
        if(s.length() >= 16) s = s.substring(0, 15);
        s = s.replaceAll("[.]$", "");
        // 7단계
        if (s.length() <= 2) {
            while (s.length() < 3)
                s += s.charAt(s.length() - 1);
        }
        return s;
    }

보다시피 정규식이 상당히 유용하다

profile
PS 블로그/Java 풀이 + 코딩테스트 정리

1개의 댓글

comment-user-thumbnail
2024년 11월 5일

Both solutions are very helpful. Thanks a lot! bubble shooter

답글 달기