티스토리 뷰

반응형

 

프로그래머스 - 비밀지도

 

이번 문제도 잘 풀었다고 생각했는데 답안 제출 후 한 분의 풀이에서 처음 보는 문법을 알게 되어 포스팅하게 되었다. 짧다고 무조건 좋은 코드는 아니겠지만, 저렇게 할 수 있는 사람은 효율적인 코드를 알면서 일부러 짧은 코드로 제출하고 있는 게 아닌가 싶다.  이 부분에 대해선 내 풀이에 대한 설명 후 적겠다. 아무튼 능력자들!

 


 

풀이 과정

내가 푼 풀이과정을 요약하면 다음과 같다. 

1. 10진수를 2진수로 변환한다. 
2. arr1, arr2의 각 숫자들을 더한다. 
3. 그 값이 0이라면 " "으로, 0보다 크다면 "#"을 출력한다. 

 

1. 10진수를 2진수로 변환한다. 

주어진 배열 두 개를 (arr1, arr2) 2진수로 바꾸고 보든 2진수가 주어진 n개의 숫자로 이뤄져야하므로 padStart를 통해 자리 수를 "0"으로 채워준다. 

  const A = arr1.map((num) => num.toString(2).padStart(n, 0));
  const B = arr2.map((num) => num.toString(2).padStart(n, 0));

 

 

2.  A, B 의 각 숫자들을 더한다. 

 

각 숫자들을 더하는 이유는 더해서 나온 숫자가 0인 것과 0보다 큰 것으로 나중에 삼항 연산자를 이용하여 공백이나 "#"을 출력하기 위함이다. 

 

A와 B의 값들은 문자열로 되어있으므로 +를 붙여 숫자로 바꿔 덧셈연산을 해준다. 이때 A, B값들 중 두 개 다  '000000'일 경우나, 0이 앞에 있는 경우에는 숫자 합이기 때문에 "0"으로 혹은 0이 생략되어 출력된다. 따라서 다시 padStart(n, 0)를 해줌으로써 자릿수 n개를 맞춰준다. padStart()는 문자열에서 가능하기 때문에 문자열로 바꿔주는 String도 사용하였다. (음 여기와 3번에서 뭔가 효율성이 떨어진다고 생각했다.)

 

A = [ '101110', '100001', '100001', '010110', '011111', '110010' ] 
B = [ '011011', '111000', '010011', '001110', '001110', '001010' ]

sumArr = [ '112121', '211001', '110012', '011220', '012221', '111020' ]
  const sumArr = [];
  for (let i = 0; i < n; i++) {
    sumArr.push(String(+A[i] + +B[i]).padStart(n, 0));
  }

 

 

 

3. sumArr의 값 하나하나를 삼항연산자를 이용해 판단하여 리턴한다.

split("")을 안쓰더라도 문자열이니 하나하나씩 map()을 사용할 수 있을 줄 알았는데 안된다. 아무튼 최종적으로 0인 값만 공백으로, 0보다 크면 "#"을 answer에 담은 후 리턴해준다. 

 const answer = [];
 for (let num of sumArr) {
    answer.push(
      num
        .split("")
        .map((item) => (item === "0" ? (item = " ") : (item = "#")))
        .join("")
    );
  }

 


 

제출 코드 

function solution(n, arr1, arr2) {
  const answer = [];
  const A = arr1.map((num) => num.toString(2).padStart(n, 0));
  const B = arr2.map((num) => num.toString(2).padStart(n, 0));
  const sumArr = [];
  for (let i = 0; i < n; i++) {
    sumArr.push(String(+A[i] + +B[i]).padStart(n, 0));
  }
  for (let num of sumArr) {
    answer.push(
      num
        .split("")
        .map((item) => (item === "0" ? (item = " ") : (item = "#")))
        .join("")
    );
  }

  return answer;
}

 

 


 

새로 알게 된 문법 - single vertical bar "|"

답을 제출한 후 한 줄로 된 답안 코드가 있었다. 

답안을 미리 보자면 아래와 같다. 

var solution=(n,a,b)=>a.map((a,i)=>(a|b[i]).toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#'))

다른 부분은 이해가 가는데 "|" 문법은 처음 보는 거라 생소해서 찾아보았다. 이 문법에 대해서는 여유가 있으면 따로 포스팅하겠다.

 

간략히 말하자면 여기서 쓰인 "|"은 2진법으로 바꾼 후에 그 값들을 더해 준 후 각 자릿수를 합해 다시 10진법으로 변환한 결과이다. 

3|4 = 7이 나오는데 이것을 코드로 풀어쓰면 아래와 같다. 

3.toString(2) = 011
4.toString(2) = 100
011 + 100 = 111
parseInt(111, 2) = 7

 

따라서 a|b[i]라 함은( a= arr1, b = arr2를 의미한다. ) arr2의 원소 하나씩과 arr1의 원소 하나씩 2진법으로 바꾼 후 합해 다시 10진법으로 바꿔주는 연산을 했다가 

 

또 그 값을 2진법으로 바꿔주는 연산을 해준 것이다. 또한 나는 정규표현식을 기피하는 병... 이 있는 것 같은데 이렇게 문제에서 빈도가 잦으니 기본적인 것들은 잘 새기고 가는 습관을 들여야겠다. 

 

 

 

 

 

Reference: 

Detailed JS operator single vertical bar "|" and "| |" Introduction to the use and role of the basic knowledge

 

 

반응형