개발조각

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

알고리즘🅰/프로그래머스

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

개발조각 2022. 2. 8. 15:06
728x90
반응형

2021.09.10에 푼 문제입니다.

 

"신규 아이디 추천" 문제 해결방안에 대해 설명하겠습니다.

프로그래머스 코딩 테스트 연습문제는 문제와 제한사항만 잘 읽고 이해만 해도 반은 푼 거라고 생각합니다.

 

 

이번 "신규 아이디 추천" 문제는
아래있는👇 1단계~7단계까지 차례대로 푸는 게 가장 베스트라는 생각이 들었습니다.

 

그리고 이문제는 "무조건 replace에 정규식으로 풀어야겠다." 라는 생각이 들었습니다.

 

 

replace에 대해  설명하자면

MDN Web Docs
replace() 메서드는 어떤 패턴에 일치하는 일부 또는 모든 부분이 교체된 새로운 문자열을 반환합니다.
그 패턴은 문자열이나 정규식(RegExp)이 될 수 있으며, 교체 문자열은 문자열이나 모든 매치에 대해서 호출된 함수일 수 있습니다.

구문: 바꿔야되는 문자열.replace("찾을 문자열", "변경할 문자열")

 

정규식을 쓰는 방법은 두가지가 있습니다.

MDN Web Docs
1. 정규식 리터럴(슬래쉬"/"로 감싸는 패턴)을 사용하는 방법
var re = /ab+c/;

2. RegExp 객체의 생성자 함수를 호출하는 방법
var re = new RegExp("ab+c");

일반적으로는 1번 방법을 많이 쓰기 때문에 1번 방법으로 사용하겠습니다.

 

그리고 정규식을 작성할 때 바로 쓰기 어려워서 아래에 있는 사이트에서 확인하면서 작성했습니다.~😊

RegExr: Learn, Build, & Test RegEx

 

RegExr: Learn, Build, & Test RegEx

RegExr is an online tool to learn, build, & test Regular Expressions (RegEx / RegExp).

regexr.com

 


해결방안

function solution(new_id) {
    // 1단계    
    new_id = new_id.toLowerCase();
    
    // 2단계
    new_id = new_id.replace(/[^a-z0-9|\-|_|.]/g,'');
    
    // 3단계
    new_id = new_id.replace(/\.+/g,'.');
    
    // 4단계
    new_id = new_id.replace(/^\.|\.$/g,'');
    
    // 5단계
    if(new_id.length === 0) new_id = new_id + 'a';
    
    // 6단계
    if(new_id.length > 15) new_id = new_id.slice(0, 15);
    new_id = new_id.replace(/\.$/g,'');

    // 7단계
    let lastChar = new_id.charAt(new_id.length-1);
    for(let i = new_id.length; i<3; i++) new_id = new_id + lastChar;
    
    return new_id;
}

 

 

1단계

toLowerCase()를 사용하여 대문자를 소문자로 고쳤습니다.

MDN Web Docs
toLowerCase() 메서드는 문자열을 소문자로 변환해 반환합니다.

구문 : str.toLowerCase()

 

"...!@BaT#*..y.abcdefghijklm" → "...!@bat#*..y.abcdefghijklm"

 

 

2단계

"알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거"라는 문구이 있어 정규식으로 표현해 주었습니다.

 

/[^a-z0-9|\-|_|.]/g

  • 알파벳 소문자(a~z) : a-z
  • 숫자(0~9) : 0-9
  • 빼기(-), 밑줄(_), 마침표(.) : |\-|_|.
  • | : 또는과 의미가 비슷합니다.
  • \ : 특정한 특수문자는 작동이 안 될 때가 있어서 안될 경우 \를 사용하시면 잘 작동됩니다.
  • [^] : "^"는 부정의 의미입니다.
  • g : 전체 매칭

 

앞에서 얘기했던 정규식 확인 사이트에서 확인해보면

알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자 표시
예1에 적용

여기서 더 짧게 쓰고 싶다면 "a-z0-9"대신 "\w"를 써주어 "/[^\w|\-|_|.]/g" 이렇게 쓰기도 하는데

  • \w : a~z, A~Z, 0~9

저는 알아보기도 좋고 문구 내용을 보다 정확하게 쓰기 위해 "a-z0-9"를 썼습니다.

 

 

앞에서 replace는 바꿔야되는 문자열.replace("찾을 문자열", "변경할 문자열") 써야 된다고 했기 때문에

  • 찾을 문자열에 /[^a-z0-9|\-|_|.]/g
  • 변경할 문자열에 '' (즉 공백)

넣어주었습니다.

 

"...!@bat#*..y.abcdefghijklm" → "...bat..y.abcdefghijklm"

 

3단계

2단계와 마찬가지로 replace와 정규식을 사용했습니다.

3단계에서는 "마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환"에서는 정규식의 +를 사용해주었습니다.

 

/\.+/g

  • + :  1회 이상 반복
  • \.+ : "."이 1회 이상 반복되면

예1에 적용

"...bat..y.abcdefghijklm" → ".bat.y.abcdefghijklm"

 

4단계

2단계, 3단계와 마찬가지로 replace와 정규식을 사용했습니다.

4단계에서는 "마침표(.)가 처음이나 끝에 위치한다면 제거"에서 ^, $사용해주었습니다.

 

 

/^\.|\.$/g

  • ^ : 처음
  • $ : 끝
  • ^\. : 첫 글자가 "."인 거 표시
  • \.$ : 마지막 글자가 "."인 거 표시

마침표(.)가 처음이나 끝에 위치한다면 제거
예1에 적용

".bat.y.abcdefghijklm" → "bat.y.abcdefghijklm"

 

5단계

"빈 문자열이라면, new_id에 "a"를 대입"하라 하여 if문을 사용했습니다.

 

if(new_id.length === 0){new_id = new_id + 'a';}

  • 빈 문자열이라면 : if(new_id.length === 0)
  • new_id에 "a"를 대입 : new_id = new_id + 'a';
"bat.y.abcdefghijklm" → "bat.y.abcdefghijklm"

 

6단계

6단계에서는 두 가지의 경우를 구해야 해서 두줄로 썼습니다.

 

첫 번째 줄

"new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거"하라 하여 if문, slice를 사용했습니다.

MDN Web Docs
slice() 메서드는 어떤 배열의 begin부터 end까지(end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환합니다. 원본 배열은 바뀌지 않습니다.

구문 : 배열.slice(배열의 시작 index, 배열의 종료 index);

만약 배열.slice(0,3); -> 배열 0부터 2까지 추출

 

slice는 배열 뿐만 아니라 문자열에서도 사용 가능합니다.

구문 : 문자열.slice(문자열 시작 index, 문자열 종류 index);

만약 문자열.slice(0,3); -> 문자열 0부터 2까지 추출

 

 

if(new_id.length > 15){new_id = new_id.slice(0, 15);}

  • new_id의 길이가 16자 이상 : if(new_id.length > 15)
  • new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거 : new_id.slice(0, 15);
  • new_id.slice(0, 15); : new_id 문자열 0번부터 14번 부분만 리턴
    -> 15개 문자까지이기 때문에 0~14(15개)까지만 허용

 

두 번째 줄

replace와 정규식을 사용했습니다.

"만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다."에서 $를 사용했습니다.

 

/\.$/g

  • $ : 끝
  • \.$ : 마지막 글자가 "."인 거 표시
"bat.y.abcdefghijklm" → "bat.y.abcdefghi"

 

7단계

7단계도 6단계와 마찬가지로 두줄로 썼는데요.

"길이가 2자 이하라면, 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다."임으로

  1. 문자열의 마지막 문자를 반환합니다.
  2. 마지막 문자를 길이가 3이 될 때까지 반복해서 끝에 붙입니다.

로 구성하여 구하였습니다.

 

첫 번째 줄

"문자열의 마지막 문자를 반환"하기 위해 charAt()함수를 사용했습니다.

charAt() 함수는 문자열에서 특정 인덱스에 위치하는  유니코드 단일 문자를 반환합니다. 

구문 : 문자열.charAt(index);

 

let lastChar = new_id.charAt(new_id.length-1);

  • 마지막 문자열의 index값 : new_id.length-1

 

두 번째 줄

"마지막 문자를 길이가 3이 될 때까지 반복해서 끝에 붙입니다."하기 위해 for문을 사용했습니다.

 

for(let i = new_id.length; i<3; i++) new_id = new_id + lastChar;

  • let i에  new_id.length을 대입하여 new_id.length(즉 new_id의 길이)가 2 이하인 것만 반복하게 했습니다.
  • 반복할 때마다 마지막 문자를 new_id 끝에 붙입니다. : new_id = new_id + lastChar;
  • 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다. : 
     for(let i = new_id.length; i<3; i++){new_id = new_id + lastChar;}
"bat.y.abcdefghi" → "bat.y.abcdefghi"

 


프로그래머스 신규 아이디 추천 해결방안 설명은 여기까지입니다.

728x90
반응형
Comments