네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.
매개변수 | 값 |
---|---|
n | 5 |
arr1 | [9, 20, 28, 18, 11] |
arr2 | [30, 1, 21, 17, 28] |
출력 | ["#####","# # #", "### #", "# ##", "#####"] |
매개변수 | 값 |
---|---|
n | 6 |
arr1 | [46, 33, 33 ,22, 31, 50] |
arr2 | [27 ,56, 19, 14, 14, 10] |
출력 | ["######", "### #", "## ##", " #### ", " #####", "### # "] |
어휴, 문제가 길다. 하지만 그림과 입출력 예제를 보고 규칙만 잘 찾는다면 쉽게 이해할 수 있다.
문제에서 힌트를 주었다. 바로 이진수이다.
10진수를 2진수로 변환하는 방법을 알아보자.
Number.prototype.toString(): 특정한 Number 객체를 나타내는 문자열을 반환한다. 매개변수로 수의 값을 나타내기 위해 사용되기 위한 기준을 정하는 2와 36사이의 정수를 담을수 있다. 더 알아보기
즉, toString(2)를 사용해 이진수로 문자열을 반환할 수 있다.
아래의 그림은 비트연산자의 설명이다. 이번 문제에서 벽("#")은 OR(|)
조건을 성립한다.
그럼 공백(" ")은 AND연산이잖아? 이라는 궁금증이 생길 것이다. 아래 그림을 보면 궁금증을 해결할 수 있다.
위의 그림을 보면 OR연산 하나로 공백(" ")과 벽("#")의 조건을 모두 성립하는 것을 볼 수 있다.
function solution(n, arr1, arr2) {
var answer = [];
for(let i=0; i<n; i++){
// toString(2)은 이진수로 반환하는 것.
const bin = (arr1[i] | arr2[i]).toString(2);
// console.log(bin);
let line = [];
for(let j = bin.length-n; j<bin.length; j++) { // j가(인덱스값)이 -1일 경우 undefined 반환.
if(bin[j] === '1') { // 1이면 '#', 그 외 ' '
line.push('#');
} else {
line.push(' ');
}
}
answer.push(line.join(''));
}
return answer;
}
코드를 풀이하자면,
1001
인데 n(=5)의 자릿수보다 부족하다. 이럴 땐, 예제 그림과 같이 01001
로 만들어주어 처리해야한다.padStart():현재 문자열의 시작을 다른 문자열로 채워, 주어진 길이를 만족하는 새로운 문자열을 반환한다. 채워넣기는 대상 문자열의 시작(좌측)부터 적용된다. 더 알아보기
j = bin.length-n
을 해주면 된다. 그 이유는 바로 뒤에 나오는 if문을 보면 알 수 있다.bin.length-n
을 하면 보통은 0이 된다. 예외적으로 9와 같은 네자리 이진수들은 -1이 될 것이다. 그리고 if문을 사용해 bin[j]
가 1일 경우에만 "#"으로 변환해주고, 그 외 모든 것들은 " "으로 변환한다.bin[-1]
는 undefined
를 반환한다. 그러므로 else에 해당된다.line[]
에는 ["#"," ","#"," ","#"]
이런 형태로 담기게 될 것이다. 출력 형식에 맞춰주기 위해 join()메서드를 사용한다. Array.prototype.join(): 배열의 모든 요소를 연결해 하나의 문자열로 만든다. 더 알아보기
다른 사람의 풀이로 공부를 하다가 정규표현식을 이용해 간단히 풀이한 것을 보고 새롭게 다가와 추가한다.
var solution=(n,arr1,arr2)=>arr1.map((a,i)=>(a|arr2[i]).toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#'))
String.prototype.replace(): 어떤 패턴에 일치하는 일부 또는 모든 부분이 교체된 새로운 문자열을 반환한다. 그 패턴은 문자열이나 정규식(RegExp)이 될 수 있으며, 교체 문자열은 문자열이나 모든 매치에 대해서 호출된 함수일 수 있다. 더 알아보기
개인적으로 내 풀이보다 위의 풀이가 더 직관적이고 맘에 든다. 내 풀이에선 1은 "#"으로 변환하고, 그 외는 모두 ' '으로 변환하게 하였는데 이것이 나중에 충분한 오류를 범할 수 있을 것이다. 또 나는 새로운 배열에 변환값을 담아 출력되는 answer 배열에 push하는 방식으로 풀었는데, 위의 풀이는 replace()메서드로 배열 자체의 요소를 변환해버린다.
이번 문제는 되게 고영양 문제였던 것 같다. 한 문제를 풀면서 배운 점이 되게 많았다. 이진수로 변환하는 법과 비트 연산자, 새로운 메서드들..
이진수를 변환하는 과정을 메서드를 사용하지 않고 코드로 풀어내는 풀이를 보았는데, 친절한 메서드를 사용하지 않는 것이 더 바람직하지 않다고 생각하여 메서드를 사용했다. 그래도 이진수를 코드로 풀어내는 과정에서 얻는 지식이 있었다!
또, 처음에 비트연산자를 사용하지 않고 조건문을 이용해 풀면 되겠다 생각했었는데, 이 문제의 출제 의도가 비트 연산자를 잘 다룰 수 있는지를 보는 것이였기 때문에 의도에 맞게 비트 연산자를 배워 사용했다. 비트 연산자 최고 👍
설명이 좋네요 감사합니다!