4 minute read



입출력 예시

Input-1
“…!@BaT#*..y.abcdefghijklm”
Output-1
“bat.y.abcdefghi”

Input-2
“z-+.^.”
Output-2
“z–“

Input-3
”=.=”
Output-3
“aaa”

Input-4
“abcdefghijklmn.p”
Output-4
“abcdefghijklmn”


문제 풀이

주어진 입력문자열을 단계별로 검증하고 변경해야 한다.
그럼 단계별로 순차적으로 아이디를 검증해보자.

단계별 풀이

1단계 문자열을 순회하며 대문자가 있을 경우 소문자로 변환하여 저장하자.

1
2
3
4
5
char[] new_id_arr = new_id.toCharArray(); // char형 입력문자열
for(int i=0; i<new_id.length(); i++) {
    char id = new_id.charAt(i);
    if(Character.isUpperCase(id)) new_id_arr[i] = Character.toLowerCase(id);
}


2단계 입력문자열에서 소문자와 숫자, “.”, “-“, “_” 문자만 answer에 담는다.

1
2
3
4
5
String answer = "";
for(int i=0; i<new_id_arr.length; i++) {
    char id = new_id_arr[i];
    if(('a'<=id && 'z'>=id) || ('0'<=id && '9'>=id) || id=='.' || id=='-' || id=='_') answer += id;
}


3단계 연속된 마침표가 존재할 경우 하나의 마침표로 치환하기 위해 replaceAll() 메서드로 정규표현식을 활용합니다.

1
answer = answer.replaceAll("\\.+", ".");

str.replaceAll("\\.+", “.”)
정규식 "\."는 마침표를 나타낸다. 그리고 “+”는 1번 이상을 의미합니다.

즉, “\s+”는 1개 이상 존재하는 마침표임을 알 수 있다.
따라서, 위 코드는 연속되는 마침표를 하나의 마침표로 치환할 수 있다.


4단계 문자열의 양쪽 끝에 마침표가 존재할 경우 제거해야 한다.
직접 문자열 배열 내 원소를 제거하는 것보다 substring()을 통한 슬라이싱을 활용하였다.

1
2
3
4
5
6
7
if(answer.length() > 1) {
    if(answer.charAt(0)=='.') answer = answer.substring(1, answer.length());
    if(answer.charAt(answer.length()-1)=='.') answer = answer.substring(0, answer.length()-1);
}
else if(answer.length() > 0 && answer.length()==1) {
    if(answer.charAt(0)=='.') answer = "";
}


5단계 4단계까지 실행 한 문자열이 빈 문자열일 경우 “a” 문자를 대입한다.

1
if(answer.equals("") || answer.isEmpty() || answer==null) answer += "a";


6단계 문자열 길이가 16자 이상일 경우 처음부터 15자 까지만 자른 후 4단계와 동일하게 양쪽 끝 마침표를 제거한다.

1
2
3
4
if(answer.length()>=16) answer = answer.substring(0, 15);
// 4단계 재실행
if(answer.charAt(0)=='.') answer = answer.substring(1, answer.length());
if(answer.charAt(answer.length()-1)=='.') answer = answer.substring(0, answer.length()-1); 

동일한 코드기에 4단계를 한 번 더 실행하도록 고치면 좋을 겉 같다.


7단계 6단계까지 실행 한 문자열의 길이가 2자 이하일 경우 3글자가 될때까지 제일 마지막 글자를 반복해서 대입한다.

1
2
3
4
5
if(answer.length()<=2) {
    while(answer.length()!=3) {
        answer += answer.charAt(answer.length()-1);
    }
}


함수형 로직으로 변경

단계별로 풀이한 코드를 보니, 단계별 기능들이 모두 다르거나 같은 기능을 내포하고 있었다.
가독성을 높이기 위해 각 단계별 코드를 함수형으로 분리하여 재작성하였다.
자세한 코드 내용은 아래 작성코드에 첨부하였다.


작성 코드

작성 코드 - 단계별 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
    public String solution(String new_id) {
        String answer = "";
        char[] new_id_arr = new_id.toCharArray();
        // 1단계
        for(int i=0; i<new_id.length(); i++) { 
            char id = new_id.charAt(i);
            if(Character.isUpperCase(id)) new_id_arr[i] = Character.toLowerCase(id);
        }
        // 2단계
        for(int i=0; i<new_id_arr.length; i++) {
            char id = new_id_arr[i];
            if(('a'<=id && 'z'>=id) || ('0'<=id && '9'>=id) || id=='.' || id=='-' || id=='_') answer += id;
        }
        // 3단계
        answer = answer.replaceAll("\\.+", ".");
        // 4단계
        if(answer.length() > 1) {
            if(answer.charAt(0)=='.') answer = answer.substring(1, answer.length());
            if(answer.charAt(answer.length()-1)=='.') answer = answer.substring(0, answer.length()-1);
        }
        else if(answer.length() > 0 && answer.length()==1) {
            if(answer.charAt(0)=='.') answer = "";
        }
        // 5단계
        if(answer.equals("") || answer.isEmpty() || answer==null) answer += "a";
        // 6단계
        if(answer.length()>=16) answer = answer.substring(0, 15);
        if(answer.charAt(0)=='.') answer = answer.substring(1, answer.length());
        if(answer.charAt(answer.length()-1)=='.') answer = answer.substring(0, answer.length()-1); 
        // 7단계
        if(answer.length()<=2) {
            while(answer.length()!=3) {
                answer += answer.charAt(answer.length()-1);
            }
        }
        return answer;
    }
}

작성코드 - 함수형 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class Solution {
    public String solution(String new_id) {
        String answer = "";
        char[] new_id_arr = step1(new_id);
        answer = step2(new_id_arr);
        answer = step3(answer);
        answer = step4(answer);
        answer = step5(answer);
        answer = step6(answer);
        answer = step7(answer);
        return answer;
    }
    private static char[] step1(String new_id) {
        char[] new_id_arr = new_id.toCharArray();
        for(int i=0; i<new_id.length(); i++) {
            char id = new_id.charAt(i);
            if(Character.isUpperCase(id)) new_id_arr[i] = Character.toLowerCase(id);
        }
        return new_id_arr;
    }
    private static String step2(char[] new_id_arr) {
        String answer = "";
        for(int i=0; i<new_id_arr.length; i++) {
            char id = new_id_arr[i];
            if(('a'<=id && 'z'>=id) || ('0'<=id && '9'>=id) || id=='.' || id=='-' || id=='_') answer += id;
        }
        return answer;
    }
    private static String step3(String answer) {
        return answer.replaceAll("\\.+", ".");
    }
    private static String step4(String answer) {
        if(answer.length() > 1) {
            if(answer.charAt(0)=='.') answer = answer.substring(1, answer.length());
            if(answer.charAt(answer.length()-1)=='.') answer = answer.substring(0, answer.length()-1);
        }
        else if(answer.length() > 0 && answer.length()==1) {
            if(answer.charAt(0)=='.') answer = "";
        }
        return answer;
    }
    private static String step5(String answer) {
        if(answer.equals("") || answer.isEmpty() || answer==null) answer += "a";
        return answer;
    }
    private static String step6(String answer) {
        if(answer.length()>=16) answer = answer.substring(0, 15);
        answer = step4(answer);
        return answer;
    }
    private static String step7(String answer) {
        if(answer.length()<=2) {
            while(answer.length()!=3) {
                answer += answer.charAt(answer.length()-1);
            }
        }
        return answer;
    }
}

회고

  • 모듈 내에서 여러 기능들을 어떻게 분리할 것이고, 공통사항은 어떻게 합칠 것인지 고민하는 과정이 단순히 알고리즘 공부를 넘어 자바를 자바답게 활용하는 데 큰 도움이 될 것이라고 느꼈다.
  • replaceAll() 메서드에서 활용할 자주 쓰이는 정규표현식들을 공부해야겠다.