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

Lenny·2022년 1월 7일
0
post-thumbnail

신규 아이디 추천

프로그래머스 Level 1 에 있는 문제이다.

문제

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

나의 풀이

function solution(new_id) {
    // 아이디의 길이는 3자 이상 15자 이하
    // 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.) 문자만 사용 가능
    // 마침표(.)는 처음과 끝에 사용할 수 없으며 또한 연속으로 사용할 수 없다.
    var answer = '';
    var reg = /[._-]|[\w]|[\d]/g; // 알파벳 소문자, 숫자, 빼기, 밑줄, 마침표만 필터하는 정규식
    var dotReg = /\.{2}/g; // ..을 검출하는 정규식
    // 1단계 : 전체 소문자 만들기
    var id = new_id.toLowerCase();
    // 2단계 : 알파벳 소문자, 숫자, 빼기, 밑줄을 제외시키고 배열을 문자열로 만들기
    id = id.match(reg).join("");
    // 3단계 : .. < 없애기
    while(true){
        id = id.replace(dotReg, ".");
        if(id.search(dotReg) === -1){
            break;
        }
    }
    // 4단계 : 문자열의 첫번째가 마침표로 끝날경우, 마침표 제거
    if(id[0] === ".") {
        id = id.substring(1);
    } // 끝이 마침표로 끝날경우, 마침표 제거
    if(id[id.length - 1] === ".") {
        id = id.substring(0, id.length - 1);
    }
    // 5단계 : 문자열이 비어있으면 a로 치환하기
    if(id === ""){
        id = "a";
    }
    // 6단계 : id의 길이가 16자 이상이면, 15자 이후로 자르고,
    if(id.length >= 16) {
        id = id.substring(0, 15);
        if(id.endsWith('.')) { // 만약 끝에 있는 문자열이 마침표이면, 마침표 제거
            id = id.substring(0, id.length - 1);
        }
    }
    // 7단계 : 문자열의 길이가 2이하일 경우 마지막 문자를 길이가 3이 될때까지 반복
    if(id.length <= 2) {
        for(var i = id.length; i < 3; i++ ){
            id += id.charAt(id.length - 1);
        }
    }
    answer = id;
    return answer;
}

나의 풀이같은 경우는 되게 하드코딩으로 풀었다.
문제에 제시 된 단계를 보고, 그걸 그대로 if문과 반복문을 써서 풀었다.
정규식도 잘 몰라서 푸는데 꽤 오래걸린것같다.

다른 사람의 풀이

보고 감탄한 다른사람의 풀이이다.
정규식과 replace를 이용해서 이렇게 심플하게 풀 수도 있구나 느꼈다. 한수 배웠다..

const solution = (new_id) => {
    const id = new_id
        .toLowerCase() // 1
        .replace(/[^\w\d-_.]/g, '') // 2
        .replace(/\.{2,}/g, '.') // 3
        .replace(/^\.|\.$/g, '') // 4
        .padEnd(1, 'a') // 5
        .slice(0, 15) // 6
        .replace(/^\.|\.$/g, '')        
    return id.padEnd(3, id[id.length-1]) // 7
}

우선 이 코드를 보면 메서드 체이닝과 replace를 이용해서 간단하게 풀었다.
우선 이 코드를 해석하려면 각 정규식이 어떤 역할을 하는지 해석이 필요했다.
먼저 주석에 번호를 달아놓았으니, 번호대로 차례대로 해석해보려고한다.

  1. toLowerCase() 라는 문자열 메서드를 사용해서, 문자열을 전부 소문자로 바꿔준다.
  2. 영어, 숫자, -, _, . 를 제외한 나머지를 선택하는 정규식이다. 즉 특수문자를 '' 빈 문자열로 replace 해준다.
  3. ".." 을 검출하는 정규식이다. 문자열 내의 .. 을 . 으로 바꿔준다.(replace)
  4. 문자열 내의 첫번째 또는 마지막 문자의 . 을 검출하는 정규식이다. 문자열의 첫번째 또는 마지막이 . 일 경우 없애준다. (replace)
  5. padEnd 메서드는 현재 문자열에 다른 문자열을 채워, 주어진 길이를 만족하는 새로운 문자열을 반환하는 메서드이다. 현재 문자열의 길이가 0 이면 1까지 'a'로 채워준다는 의미이다. 자세한 사용법은https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd 를 참고
  6. 문자열의 길이를 15까지 자르고, 다시 정규식을 적용한다. 여기서 나온 정규식은 4번과 같은 역할을 한다. (맨 앞 또는 맨 뒤의 .< 을 체크하고 없애준다.)
  7. 현재 문자열의 길이가 3보다 작으면, 현재 문자열이 들어있는 배열의 마지막 문자로 채워준다. ex) 현재 문자열이 "a" 이고, padEnd(3, id[id.length - 1]) 이라면, aaa가 됨. 만약 padEnd(3, "z") 라면, azz가 된다. 이게 padEnd..

여기까지 다른 사람이 작성한 코드를 해석해봤다.
해석하면서 정규식 공부도 조금 된 것 같다 ㅋㅋㅋㅋㅋ

나는 이 문제를 푸는데 체감상 거의 한 시간 ~ 두 시간 정도 걸린것같다.
그래도 다른 사람의 코드를 먼저 보지않고, 자바스크립트 docs 를 뒤적거리면서 풀었다는게 되게 뿌듯했다.
그리고 이 문제를 풀면서 정규식의 형태?? 에서도 천천히 둘러볼 수 있어서 좋았다.
정규식은 시간 날 떄 틈틈히 활용하는 연습을 해봐야겠다.

https://regex101.com/ < 정규식 연습하는 사이트!

profile
🧑‍💻

0개의 댓글