본문 바로가기
알고리즘 문제 풀기 연습

codewars.com 문제 풀기1

알고리즘 연습 1.

우연히 codewars.com 을 알게되었는데, 비교적 어렵지 않은 문제들이 출제된다고 한다 해서 오늘부터 진행할 생각이다.

 

대망의 첫번 째 문제.

 

Usually when you buy something, you're asked whether your credit card number, phone number or answer to your most secret question is still correct. However, since someone could look over your shoulder, you don't want that shown on your screen. Instead, we mask it.

Your task is to write a function maskify, which changes all but the last four characters into '#'.

 

그러니까 예를들면, "크레딧카드 번호가 있다고 가정한다면 뒤에 4자리만 숫자를 보여주고

나머지는 문자열은 # 로 표현되도록 리턴하라" 이다. 따라서, 예상 리턴 값은 "####1234" 이다.

 

 

#처음 풀었던 코드

function maskify(cc) {
  const STAR = '#';
  let index = cc.length - 4;
  let result = '';
  for (let i = 0; i < cc.substring(0, index).length; i++) {
    result += STAR;
  }
  return result.concat(cc.slice(index));
}
console.log(maskify(cc));

오류가 난다. 이유는 cc 라는 문자열의 길이가 4개를 넘지 않을 때를 생각하지 못했기 때문이다.

4자리를 넘지 않을 때, 즉 n, nn, nnn, nnnn 이 들어갔을 때 그대로 반환해야 하는데,

특히 nnn 이 들어가면 n 이 나온다.

따라서, 마지막 4자리만 보여주고, 그 앞의 문자를 #로 바꿔라 라는 문제에서 적절한 예외 처리를 반드시 해주어야 한다.

라고 생각했지만, 자바스크라서 그런지 예외 처리를 반드시 하지 않아도 원하는 값을 얻을 수 있는 것 같았다.

 

 

#두번째 풀었던 코드

function maskify(cc) {
  const STAR = '#';
  if (cc.length > 4) {
    let index = cc.length - 4;
    let result = '';
    for (let i = 0; i < index; i++) {
      result += STAR;
    }
    return (cc = result.concat(cc.slice(index)));
  } else {
    return cc;
  }
}
console.log(maskify(cc));

이 코드로 테스트 해보면 오류가 없다. 테스트 통과.

하지만 아쉽다. 선언된 변수가 많고, 반복문을 돌린다는거 자체가 뭔가 창의적이지 않다는 느낌이다.

거기에 더해서 4라는건 매직넘버이다.

 

 

#세번째 코드

function maskify(cc) {
  const STAR = '#';
  const SHOW_NUMLINE = 4;
  if (SHOW_NUMLINE < cc.length) {
    let index = cc.length - SHOW_NUMLINE;
    return cc.substring(0, index).split('').fill(STAR, 0).join('').concat(cc.slice(index));
  } else {
    return cc;
  }
}
console.log(maskify(cc));

이 코드도 통과.

let result 를 선언하기 싫어서, 파라미터 값 cc 만을 가지고, 배열을 만들어서 메서드를 체이닝 했다.

과연 이게 더 좋은 코드인지는 모르겠으나, 스트링과 배열의 메서드 공부는 된 것 같다.

생각한 로직은 끝에 4자리를 기준으로 하여, 그 앞의 문자 길이를 전부 # 로 바꿔주는 것이다.

 

 

#그 외 신박한 풀이 방법

function maskify(cc) {
  return cc.slice(0, -4).replace(/./g, '#') + cc.slice(-4);
}

function maskify(cc) {
  return cc.replace(/.(?=....)/g, '#');
}

function maskify(cc) {
  return cc.replace(/.(?=.{4})/g, "#");
}

maskify = (cc) => '#'.repeat(Math.max(0, cc.length - 4)) + cc.substr(-4);

const maskify = cc => cc.slice(-4).padStart(cc.length, '#')

function maskify(cc) {
  var x = cc.length - 4;
  return x > 0 ? new Array(x + 1).join('#') + cc.slice(x) : cc;
}

function maskify(cc) {
  return cc.split('').map((v,i,a) => a.length - i > 4 ? '#' : v).join('')
}

function maskify(cc) {
  const preserveCharacterCount = 4;
  
  if (cc.length <= preserveCharacterCount) {
    return cc;
  }
  
  const charCountToMask = cc.length - preserveCharacterCount;
  
  return (new Array(charCountToMask).fill('#')).join('') 
    + cc.substr(charCountToMask, preserveCharacterCount);
}

개인적으로 중간에 arrow function 을 사용한 것이 가장 깔끔한 것 같지만, 예외 처리가 적절하진 않은 것 같다.