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

Chaejung·2022년 10월 21일
1

알고리즘_JavaScript

목록 보기
5/12

문제


level1이라서 에이 금방 끝나겠지 싶었는데, 왠걸?
거의 1시간 반 걸렸다...
난 아직 자바스크립트랑 많이 안 친한갑다...
아무튼 문자열을 검사하고 조건에 맞게 수정하면 되는 문제이다.
그런데 1시간 반 걸린 이유 중 하나는,
문제를 잘못 이해해서 입력값을 수정해야하는지, 안 해야하는지 검사하는 함수를 만드느라 지체된 것이다.

해설 코드

// 두 번째 단계
// 1단계 처리 후 값에서 알파벳, 소문자, 숫자, '-', '_', '.'을 제외한 모든 문자를 제거합니다.
function step2(input_id) {
  let remove_irrelavant = "";
  for (let i = 0; i < input_id.length; i++) {
    if (/[0-9a-z]/g.test(input_id[i])) {
      remove_irrelavant += input_id[i];
    } else if (
      input_id[i].includes("_") ||
      input_id[i].includes(".") ||
      input_id[i].includes("-")
    ) {
      remove_irrelavant += input_id[i];
    }
  }
  return remove_irrelavant;
}

// 세 번째 단계, 네 번째 단계
// 2단계 처리 후 값에서 '.'가 2번 이상 연속된 부분을 하나의 '.'로 치환하고, 이때 '.'가 처음이나 끝에 위치하면 제거한다.
function step3and4(input_id) {
  let removed_dots = "";
  for (let i = 0; i < input_id.length; i++) {
    if (removed_dots == "") {
      if (input_id[i] == ".") {
        continue;
      }
      removed_dots += input_id[i];
      continue;
    }
    if (removed_dots[removed_dots.length - 1] == "." && input_id[i] == ".") {
      continue;
    }
    if (i == input_id.length - 1 && input_id[i] == ".") {
      continue;
    }
    removed_dots += input_id[i];
  }
  if (removed_dots.endsWith(".")) {
    removed_dots = removed_dots.slice(0, removed_dots.length - 1);
  }
  return removed_dots;
}

// 여섯 번째 단계 + 일곱 번째 단계
// 5단계 처리 후 길이가 16자 이상이면 15개의 문자열 제외한 것을 제거하거나 길이가 2자 이하이면 3이 될 때까지 마지막 문자를 끝에 붙인다.
function step6or7(input_id) {
  let step6_7 = input_id;
  if (input_id.length >= 16) {
    step6_7 = input_id.slice(0, 15);
    if (step6_7.endsWith(".")) {
      step6_7 = step6_7.slice(0, 14);
    }
  } else if (input_id.length <= 2) {
    do {
      step6_7 += step6_7[input_id.length - 1];
    } while (step6_7.length < 3);
  }
  return step6_7;
}

function solution(new_id) {
  let answer = "";
  // 첫 번째 단계
  let after_step_1 = new_id.toLowerCase();
  let after_step_2 = step2(after_step_1);
  let after_step_3_4 = step3and4(after_step_2);
  // 다섯 번째 단계
  let after_step_5 =
    after_step_3_4 === "" ? (after_step_3_4 += "a") : after_step_3_4;

  if (3 <= after_step_5.length && after_step_5.length <= 15) {
    answer = after_step_5;
  } else {
    answer = step6or7(after_step_5);
  }

  return answer;
}

첫 번째 단계에서는 소문자로 전부 치환하기위해.toLowerCase()를 사용했다.
두 번째 단계에서는 특정 문자를 제외한 모든 문자를 제거하기 위해 이전에 처리된 문자를 처음부터 끝까지 돌면서 특정 문자인지 아닌지를 판별하여 맞으면 새롭게 추가하고 아니면 추가하지 않는 것으로 로직을 짰다.
세 번째와 네 번째 단계에서는 '.'를 가지고 처리하는 것이라 묶게 되었고, 이것도 마찬가지로 이전에 처리된 문자를 처음부터 끝까지 돌면서 처음과 끝을 판별하고 또 스택을 활용해 2개 이상 연속되는지 확인했다.
다섯 번째 단계에서는 삼항 연산자를 이용해 빈 문자열에 따라 나오도록 했다.
여섯 번째와 일곱 번째 단계는 결과 길이에 따라서 함수 적용을 나누었고, 16자 이상이면 slice, 아니면 while로 덧붙여주었다. 이때 자른 뒤 '.'로 끝나면 한 번 더 잘라줘야하는 게 관건이었다.

캡쳐는 못 찍었으나 8점을 받았다!

우수 코드

function solution(new_id) {
  const answer = new_id
    .toLowerCase() // 1
    .replace(/[^\w-_.]/g, "") // 2
    .replace(/\.+/g, ".") // 3
    .replace(/^\.|\.$/g, "") // 4
    .replace(/^$/, "a") // 5
    .slice(0, 15)
    .replace(/\.$/, ""); // 6
  const len = answer.length;
  return len > 2 ? answer : answer + answer.charAt(len - 1).repeat(3 - len);
}

기억해야 할 것

  • 자바스크립트는 파이썬처럼 인덱싱할 때 음수 인덱싱이 안된다.
  • 숫자 또는 소문자인지 확인하는 정규 표현식 (/[0-9a-z]/g.test(input_id[i]))
profile
프론트엔드 기술 학습 및 공유를 활발하게 하기 위해 노력합니다.

0개의 댓글