와드의 블로그

신규 아이디 추천 본문

PS/프로그래머스

신규 아이디 추천

Ward 2026. 3. 12. 10:27

문제

카카오 아이디 규칙에 맞지 않는 아이디가 입력되었을 때, 입력된 아이디와 유사하면서 규칙에 맞는 새로운 아이디를 추천해 주는 문제입니다.

다음 7단계의 순차적인 처리 과정을 거쳐야 합니다.

  1. 모든 대문자를 대응되는 소문자로 치환합니다.
  2. 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
  3. 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
  4. 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
  5. 빈 문자열이라면, "a"를 대입합니다.
  6. 길이가 16자 이상이면, 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다. 만약 제거 후 마침표(.)가 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
  7. 길이가 2자 이하라면, 마지막 문자를 길이가 3이 될 때까지 반복해서 끝에 붙입니다.

링크: https://school.programmers.co.kr/learn/courses/30/lessons/72410

풀이 1: 문자열 파싱

문자열을 순회하며 단계별로 구현합니다. StringBuilder와 문자열 순회만으로 7단계를 완벽하게 처리합니다.

  • 1단계 & 2단계: toLowerCase()를 통해 소문자로 바꾼 뒤, 조건문(c >= 'a' && c <= 'z' 등)을 활용해 허용된 문자만 StringBuilder에 담습니다.
  • 3단계 (핵심 로직): 마침표(.)의 연속 여부를 파악할 때 인덱스를 직접 다루면 에러가 발생하기 쉽습니다. 대신 tmp라는 변수에 방금 전 처리한 문자를 저장해 두고, 현재 문자와 tmp가 모두 마침표라면 건너뛰는(continue) 방식을 사용하여 인덱스 에러 없이 안전하게 연속된 마침표를 압축했습니다.
  • 4단계 ~ 7단계: startsWith, endsWith, substring, length 등 자바의 내장 String 메서드들을 적절히 활용하여 문자열의 길이나 앞뒤 조건을 제어합니다.

코드 1: 문자열 파싱

class Solution {
    public String solution(String new_id) {
        // 1단계: 소문자 치환
        String id = new_id.toLowerCase();

        // 2단계: 허용되지 않는 문자 제거
        StringBuilder sb = new StringBuilder();
        for (char c : id.toCharArray()) {
            if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.') {
                sb.append(c);
            }
        }
        id = sb.toString();

        // 3단계: 연속된 마침표(.) 압축
        sb = new StringBuilder();
        char tmp = '\\0';
        for (char c : id.toCharArray()) {
            // 이전 문자와 현재 문자가 모두 마침표라면 무시
            if (c == '.' && tmp == '.') {
                continue;
            }
            sb.append(c);
            tmp = c; // 방금 처리한 문자를 tmp에 저장
        }
        id = sb.toString();

        // 4단계: 처음과 끝의 마침표(.) 제거
        if (id.startsWith("."))
            id = id.substring(1);
        if (id.endsWith("."))
            id = id.substring(0, id.length() - 1);

        // 5단계: 빈 문자열 처리
        if (id.length() == 0)
            id = "a";

        // 6단계: 길이 16자 이상 처리
        if (id.length() >= 16) {
            id = id.substring(0, 15);
            if (id.endsWith(".")) {
                id = id.substring(0, 14);
            }
        }

        // 7단계: 길이 2자 이하 처리
        while (id.length() < 3)
            id = id + id.charAt(id.length() - 1);

        return id;
    }
}

풀이 2: 정규표현식(Regex) 활용

자바의 String.replaceAll() 메서드와 정규표현식을 활용하면 매우 짧고 선언적인 코드를 작성할 수 있습니다.

  • 2단계 ([^a-z0-9\\\\-_.]): ^ 기호는 대괄호 [] 안에서 '부정(NOT)'을 의미합니다. 즉, 영소문자, 숫자, 빼기, 밑줄, 마침표가 아닌 문자를 찾아 빈 문자열("")로 치환하여 제거합니다.
  • 3단계 (\\\\.{2,}): .은 정규식에서 특수문자이므로 \\\\.으로 이스케이프 처리합니다. {2,}는 2번 이상 반복됨을 의미하므로, 연속된 마침표를 찾아서 하나의 마침표(.)로 치환합니다.
  • 4단계 (^\\\\.|\\\\.$): ^는 문자열의 시작, $는 문자열의 끝을 의미하며, |는 OR 연산자입니다. 즉, 시작이 마침표이거나 끝이 마침표인 부분을 찾아 제거합니다.

코드 2: 정규표현식 활용

class Solution {
    public String solution(String new_id) {
        // 1단계: 소문자 치환
        String id = new_id.toLowerCase();

        // 2단계: 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자 제거
        id = id.replaceAll("[^a-z0-9\\\\-_.]", "");

        // 3단계: 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환
        id = id.replaceAll("\\\\.{2,}", ".");

        // 4단계: 마침표(.)가 처음이나 끝에 위치한다면 제거
        id = id.replaceAll("^\\\\.|\\\\.$", "");

        // 5단계: 빈 문자열이라면, "a"를 대입
        if (id.isEmpty()) {
            id = "a";
        }

        // 6단계: 길이가 16자 이상이면, 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거
        if (id.length() >= 16) {
            id = id.substring(0, 15);
            // 만약 제거 후 마침표(.)가 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거
            id = id.replaceAll("\\\\.$", "");
        }

        // 7단계: 길이가 2자 이하라면, 마지막 문자를 길이가 3이 될 때까지 반복해서 끝에 붙임
        while (id.length() < 3) {
            id += id.charAt(id.length() - 1);
        }

        return id;
    }
}

'PS > 프로그래머스' 카테고리의 다른 글

유연근무제  (0) 2026.04.02
교점에 별 만들기  (1) 2026.03.13
피로도  (0) 2026.03.12
옹알이 (2)  (0) 2026.03.11
숫자 문자열과 영단어  (0) 2026.03.11