알고리즘

[프로그래머스] 2021 카카오 신규 아이디 추천 풀이 (JavaScript)

2025-06-12 14:56


[프로그래머스] 2021 카카오 신규 아이디 추천 풀이 (JavaScript)

문제 소개

카카오 2021 BLIND RECRUITMENT에서 출제한 신규 아이디 추천 문제이다. 난이도는 level1. 사실 이 문제를 예전에 Java 로 풀어본 적이 있는데, 요즘 자바스크립트를 공부하면서 다시 풀어보고 싶었다.

➡️ 프로그래머스 문제링크


유저가 입력한 신규 아이디를 규칙에 맞는지 검사하고, 맞지 않으면 규칙에 맞는 새로운 아이디를 추천해주는 문제이다. 규칙은 다음과 같다.

  1. new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
  2. newid에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(), 마침표(.)를 제외한 모든 문자를 제거합니다.
  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이 될 때까지 반복해서 끝에 붙입니다.

규칙은 7단계로 문자열을 계속 맞게 필터링해주는 단순 구현 문제이다.

내가 푼 방식

일단 엄청 조건이 많다.ㄷㄷ 까다로운 것 같지만, 단계 별로 하나씩 바꿔서 출력해서 차근 차근 접근하면 된다. 문자열에 대한 자바스크립트 내장 함수를 잘 이용해야겠다고 생각했고 로그를 찍어보면서 디버깅했다.

생각보다 문자열을 자르는 거라 던지, 2번 이상 연속된 부분을 구하는 부분 등에서 헷갈린 부분이 많았다. 예를 들면 문자열을 자를 때 subString() 을 사용하자! 라고 생각은 했는데 인덱스에서 어디까지 잘리는지 자세한 사용법은 모르고 있었다..(역시 이래서 해봐야한다;;)

연속된 부분을 구할때도 바로 떠오르는 함수가 없었기에 단순 구현해봤다.

아래는 내가 푼 코드다.

function solution(new_id) {
  let answer = String(new_id);
  // 1단계 : 대문자 -> 소문자
  answer = answer.toLowerCase();

  // 2단계 : 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거
  let secondAnswer = '';
  for (let char of answer) {
    if (
      (char >= 'a' && char <= 'z') || // 소문자이면
      !isNaN(Number(char)) ||
      char === '-' ||
      char === '_' ||
      char === '.'
    ) {
      secondAnswer += char;
    }
  }

  // 3단계 : 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환
  let thirdAnswer = '';
  let before = '';
  for (let char of secondAnswer) {
    // . 연속이면 . 으로 바꾸기
    if (before === '.' && char === '.') {
      // 제일 마지막 글자가 . 이면 넣지 않기
      if (!thirdAnswer.endsWith('.')) {
        thirdAnswer += '.';
      }
    } else {
      thirdAnswer += char;
      before = char;
    }
  }

  // 4단계 : 마침표(.)가 처음이나 끝에 위치한다면 제거
  let fourthAnswser = thirdAnswer;
  if (thirdAnswer.startsWith('.')) {
    fourthAnswser = fourthAnswser.slice(1);
  }
  if (fourthAnswser.endsWith('.')) {
    fourthAnswser = fourthAnswser.substring(0, fourthAnswser.length - 1);
  }

  // 5단계 : 빈 문자열이라면, new_id에 "a"를 대입
  let fitthAnswer = fourthAnswser;
  if (fitthAnswer === '') {
    fitthAnswer += 'a';
  }

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

  // 7단계 : 길이가 2자 이하라면,
  // new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙임
  let seventhAnwer = sixthAnwer;

  if (seventhAnwer.length <= 2) {
    let lastChar = seventhAnwer.substring(seventhAnwer.length - 1);

    while (seventhAnwer.length < 3) {
      seventhAnwer += lastChar;
    }
  }

  return answer;
}

그냥 보기만 해도 길다😧 참고만 하고 따라 하신 마시길..결국엔 테스트 케이스를 다 통과하긴 했는데, 어딘가 맘에 안든다. 일단 변수부터 단계마다 모두 선언했고 불필요한 코드들이 많았음.. (메모리 관리 안할꺼냐..)

그래서 풀이 방식의 장단점을 정리해보았다.

장점

단점

코드가 너무 길었기 때문에 좀 더 간략하게 줄이고 싶은 마음이 컸다.

다른 사람이 푼 방식

function solution(new_id) {
  let answer = new_id
    .toLowerCase() // 1
    .replace(/[^a-z0-9_.-]/g, '') // 2
    .replace(/\.{2,}/g, '.') // 3
    .replace(/^\.|\.$/g, '') // 4
    .replace(/^$/, 'a') // 5
    .substring(0, 15)
    .replace(/\.$/, ''); // 6

  //7
  return answer.padEnd(3, answer[answer.length - 1]);
}

정규식을 사용해서 코드의 복잡성을 줄이고, 메서드 체이닝을 이용해서 쓸 데없는 변수 선언을 줄였다. 정규식으로 풀 수 있다는 걸 왜 생각을 못했을까..?? 정규식이 나는 코드적으로 확 안 와닿아서 생각이 안났는데, 모르는 사람이 보면 가독성은 안좋지만 오히려 코드가 짧아지니까 주석만 잘 쓰면 쓰는 게 좋다고 생각한다.

여기서 정규식 사용법 알아가기

.replace(/[^a-z0-9_.-]/g, "")
.replace(/\.{2,}/g, ".")

.(점)이 2개 이상 연속 된 것을 하나의 .(점) 으로 줄인다.

.replace(/^$/, "a")

그리고 마지막에 나온 padEnd() 함수는 처음 보는 녀석이어서 잘 몰랐는데, 원하는 문자열 길이만큼 끝에 문자를 덧붙여주는 함수였다.

str.padEnd(최종 문자열의 길이, 끝에 채울 문자열)
answer.padEnd(3, answer[answer.length - 1]);

문자열이 3보다 짧다면 아무일이 없겠지만, 짧으면 길이를 3만큼 늘리고, 비어있는 나머지 공간에 answer의 끝문자를 다 채워준다. 이런 함수가 없었다면 while 반복문으로 3이 될때까지 문자열을 추가해주는 로직을 반복했을 거다. 고정적인 길이를 유지하고 싶을 때 사용하면 유용하게 쓰일 것 같다.

결론




 카카오문제  코딩테스트  프로그래머스