[프로그래머스] 비밀지도
2021.12.08에 푼 문제입니다.
해결방안
function solution(n, arr1, arr2) {
var answer = [];
let arr1Bs = [];
let arr2Bs = [];
// arr1, arr2의 숫자를 2진법으로 만들고 #,공백으로 교체하기
for(let i=0; i<n; i++){
let bs1 = arr1[i].toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#').split('');
let bs2 = arr2[i].toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#').split('');
arr1Bs.push(bs1);
arr2Bs.push(bs2);
}
// 두 장의 지도를 겹쳤을 때
for(let i=0; i<n; i++){
for(let j=0; j<n; j++){
arr1Bs[i][j] === '#' || arr2Bs[i][j] === '#' ? arr1Bs[i][j] = '#' : arr1Bs[i][j] = ' ';
}
}
// 2차원배열을 1차원 배열로
for(let i=0; i<n; i++){
answer.push(arr1Bs[i].join(''));
}
return answer;
}
해결방안 순서
- arr1, arr2에 들어있는 숫자(10진수)를 2진수를 바꾸고 #, 공백으로 교체하여 2차원 배열 arr1Bs, arr2Bs 로 바꾸어주기
- 1단계에서 만든 2차원 배열 arr1Bs, arr2Bs을 비교하여 둘 중 하나 #이 있으면 #으로 아니면 공백으로 바꾸기
- 2차원 배열을 1차원 배열로 바꾸어주기
1단계. arr1, arr2에 들어있는 숫자(10진수)를 2진수를 바꾸고 #, 공백으로 교체하여 2차원 배열 arr1Bs, arr2Bs 로 바꾸어주기
var answer = [];
let arr1Bs = [];
let arr2Bs = [];
// arr1, arr2에 들어있는 숫자(10진수)를 2진수를 바꾸고 #, 공백으로 교체하여 2차원 배열 arr1Bs, arr2Bs 로 바꾸어주기
for(let i=0; i<n; i++){
let bs1 = arr1[i].toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#').split('');
let bs2 = arr2[i].toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#').split('');
arr1Bs.push(bs1);
arr2Bs.push(bs2);
}
- arr1Bs : arr1배열의 원소를 2진수로 바꾸고 #, 공백으로 교체한 값을 2차원 배열로 넣어줄 곳
- arr2Bs : arr2배열의 원소를 2진수로 바꾸고 #, 공백으로 교체한 값을 2차원 배열로 넣어줄 곳
이번에도 어김없이 for문을 사용했는데요.
여기서 for문을 사용한 이유는 arr1, arr2배열의 원소를 차례대로 바꿔주기 위해서는
for문을 사용해서 배열의 0번쨰 원소부터 시작해서 마지막 원소까지 바꾸어주는 게 좋겠다 생각이 들어서
for(let i=0; i<n; i++)를 사용했습니다.
arr1[i].toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#').split('');
- 10진수를 2진수로 : arr1[i].toString(2).padStart(n,0)
- 2진수를 0이면 공백 1이면 #으로 변경 : replace(/0/g,' ').replace(/1/g,'#')
- 2번에서 얻은 값을 쪼개기 : split('')
1단계_1.10진수를 2진수로 : arr1[i].toString(2).padStart(n,0)
먼저 10진수를 2진수로 바꾸어야 되는데요.
10진수 -> ?진수로 바꾸는 방법은 전에 "3진법 뒤집기"에서 설명했는데요.
자세한 설명은 전에 제가 설명했던 3진법 뒤집기 해결방안에서 보시면 됩니다.👇
https://development-piece.tistory.com/9
[프로그래머스] 3진법 뒤집기
2021.11.05에 푼 문제입니다. 이 문제는 어려운 건 아닌데 검색하면 금방 풀 수 있어서 쉽게 풀 수 있었던 것 같아요. 해결방안 function solution(n) { return parseInt(n.toString(3).split('')..
development-piece.tistory.com
간단하게 진법을 바꾸는 방법에 대해 설명하자면
- toString() : 10진법을 2~36사이의 진법으로 바꿀 때 사용
- parseInt() : 2~36사이의 진법을 10진법으로 바꿀 때 사용
이렇게 됩니다.
지금은 "10진법 -> 2진법"으로 바꾸려고 하니까 toString()을 사용했습니다.
여기서 toString()만쓰면 좋겠지만 이것만 쓰면 문제가 생깁니다.
만약 9라는 수를 2진법으로 바꾸자고 한다면
이 문제에서 제가 구하고 싶은 값은
9 -> 01001 이와 같이 5자리 수의 2진법인데
toString()만쓴다면 1001이 나오게 됩니다.
- 내가 얻고 싶은 수(생략 없이 5자리수) : 01001
- toString()만쓰면 나오는 수 1001
이렇게 앞자리 0이 생략하게 됩니다.
그래서 5자리수 2진법을 만들기 위해 padStart() 메서드를 사용해야 됩니다.
MDN Web Docs
padStart() 메서드는 현재 문자열의 시작을 다른 문자열로 채워, 주어진 길이를 만족하는 새로운 문자열을 반환합니다. 채워넣기는 대상 문자열의 시작(좌측)부터 적용됩니다.
구문 : str.padStart(targetLength [, padString])
- targetLength : 목표 문자열 길이. 현재 문자열의 길이보다 작다면 채워넣지 않고 그대로 반환.
- padString Optional : 현재 문자열에 채워넣을 다른 문자열. 문자열이 너무 길어 목표 문자열 길이를 초과한다면 좌측 일부를 잘라서 넣음. 기본값은 " ". (U+0020)
// padStart()메서드 예제
const str1 = '5';
console.log(str1.padStart(2, '0')); //"05"
toString(), padStart()을 사용해서 나온 값을 보자면
for(let i=0; i<n; i++){
arr1[i].toString(2).padStart(n,0);
}
테스트 1
n=5; arr1=[9, 20, 28, 18, 11]; arr2=[30, 1, 21, 17, 28];
for(let i=0; i<5; i++){
let bs1 = arr1[i].toString(2).padStart(5,0);
let bs2 = arr1[i].toString(2).padStart(5,0);
}
bs1 : 01001, 10100, 11100, 10010, 01011
bs2 : 1110, 0001, 10101, 10001, 11100
테스트 2
n=6; arr1=[46, 33, 33 ,22, 31, 50]; arr2=[27 ,56, 19, 14, 14, 10];
for(let i=0; i<5; i++){
let bs1 = arr1[i].toString(2).padStart(6,0);
let bs2 = arr1[i].toString(2).padStart(6,0);
}
bs1 : 101110, 100001, 100001, 010110, 011111, 110010
bs2 : 011011, 111000, 010011, 001110, 001110, 001010
이 됩니다.
1단계_2. 2진수를 0이면 공백 1이면 #으로 변경 : replace(/0/g,' ').replace(/1/g,'#')
앞에 1단계_1에서 n자리수 2진수를 만들었다면
이제 그 수를 가지고 0이면 공백, 1이면 #으로 변경해야 되는데요.
정규식을 활용해서 구하였습니다.
사실 for문을 사용해서 했지만...ㅎㅎ
다른 사람 풀이 보기에서 다들 정규식을 사용했더라고요.
1단계_1뒤에 .replace(/0/g,' ').replace(/1/g,'#')를 썼는데,
여기서 replace(0, '#')이 아닌 정규식(//g)을 쓴 이유는
바꿔야 되는 게(0,1) 문자열이 아닌 숫자여서 그런지 replace(0, '#') 쓰면 답이 이상하게 나오더라고요😥
- .replace(/0/g,' ') : 0을 공백으로 변경
- .replace(/1/g,'#') : 1을 #으로 변경
replace에 대한것과 replace에 정규식을 넣는 방법에 대해 자세히 알고 싶다면
제가 전에 올렸던 신규 아이디 추천 해결방안을 보시면 됩니다.👇
https://development-piece.tistory.com/1
[프로그래머스] 신규 아이디 추천
2021.09.10에 푼 문제입니다. "신규 아이디 추천" 문제 해결방안에 대해 설명하겠습니다. 프로그래머스 코딩 테스트 연습문제는 문제와 제한사항만 잘 읽고 이해만 해도 반은 푼 거라고 생각합니다
development-piece.tistory.com
for(let i=0; i<n; i++){
arr1[i].toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#')
}
테스트 1
n=5; arr1=[9, 20, 28, 18, 11]; arr2=[30, 1, 21, 17, 28];
for(let i=0; i<5; i++){
let bs1 = arr1[i].toString(2).padStart(5,0).replace(/0/g,' ').replace(/1/g,'#')
let bs2 = arr1[i].toString(2).padStart(5,0).replace(/0/g,' ').replace(/1/g,'#')
}
bs1 : 01001, 10100, 11100, 10010, 01011 -> _#__#, #_#__, ###__, _#_## (공백을 임시로 _로 표시했습니다.)
bs2 : 11110, 00001, 10101, 10001, 11100 -> ####_, ____#, #_#_#, #___#, ###__ (공백을 임시로 _로 표시했습니다.)
테스트 2
n=6; arr1=[46, 33, 33 ,22, 31, 50]; arr2=[27 ,56, 19, 14, 14, 10];
for(let i=0; i<5; i++){
let bs1 = arr1[i].toString(2).padStart(6,0);
let bs2 = arr1[i].toString(2).padStart(6,0);
}
bs1 : 101110, 100001, 100001, 010110, 011111, 110010 -> #_###_, #____#, #____#, _#_##_, _#####, ##__#_
bs2 : 011011, 111000, 010011, 001110, 001110, 001010 -> _##_##, ###___, _#__##, __###_, __###_, __#_#_
1단계_3. 1단계_2에서 얻은 값을 쪼개기 : split('')
마지막으로 1단계_2에서 얻은 값을 공백과 #을 다 쪼개었는데요,
여기서 쪼갠 이유는 2단계에서
"두 장의 지도를 겹쳤을 때 둘 중 하나 #이 있으면 #으로 아니면 공백으로 바꾸기"를 해야 되는데요.
이 문장을 코드로 작성하기 위해 합쳐진 문자열이 아닌 배열의 각각의 원소로 쪼개어 줘야지 구할 수 있습니다.
MDN Web Docs
split() 메서드는 String 객체를 지정한 구분자를 이용하여 여러 개의 문자열로 나눕니다.
구문 : str.split([separator[, limit]])
- separator Optional
원본 문자열을 끊어야 할 부분을 나타내는 문자열을 나타냅니다. 실제 문자열이나 정규표현식을 받을 수 있습니다. 문자열 유형의 separator가 두 글자 이상일 경우 그 부분 문자열 전체가 일치해야 끊어집니다. separator가 생략되거나 str에 등장하지 않을 경우, 반환되는 배열은 원본 문자열을 유일한 원소로 가집니다. separator가 빈 문자열일 경우 str의 각각의 문자가 배열의 원소 하나씩으로 변환됩니다. - limit Optional
끊어진 문자열의 최대 개수를 나타내는 정수입니다. 이 매개변수를 전달하면 split() 메서드는 주어진 separator가 등장할 때마다 문자열을 끊지만 배열의 원소가 limit개가 되면 멈춥니다. 지정된 한계에 도달하기 전에 문자열의 끝까지 탐색했을 경우 limit개 미만의 원소가 있을 수도 있습니다. 남은 문자열은 새로운 배열에 포함되지 않습니다.
// split 예제
var myString = 'Hello World. How are you doing?';
var splits = myString.split(' ', 3);
console.log(splits); //["Hello", "World.", "How"]
// limit를 안 쓸 경우
let mystring = 'Hello';
console.log(mystring.split('')); // [ 'H', 'e', 'l', 'l', 'o' ]
for(let i=0; i<n; i++){
let bs1 = arr1[i].toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#').split('');
let bs2 = arr2[i].toString(2).padStart(n,0).replace(/0/g,' ').replace(/1/g,'#').split('');
arr1Bs.push(bs1);
arr2Bs.push(bs2);
}
테스트 1
n=5; arr1=[9, 20, 28, 18, 11]; arr2=[30, 1, 21, 17, 28];
arr1Bs = [
[ ' ', '#', ' ', ' ', '#' ],
[ '#', ' ', '#', ' ', ' ' ],
[ '#', '#', '#', ' ', ' ' ],
[ '#', ' ', ' ', '#', ' ' ],
[ ' ', '#', ' ', '#', '#' ]
]
arr2Bs = [
[ '#', '#', '#', '#', ' ' ],
[ ' ', ' ', ' ', ' ', '#' ],
[ '#', ' ', '#', ' ', '#' ],
[ '#', ' ', ' ', ' ', '#' ],
[ '#', '#', '#', ' ', ' ' ]
]
테스트 2
n=6; arr1=[46, 33, 33 ,22, 31, 50]; arr2=[27 ,56, 19, 14, 14, 10];
arr1Bs = [
[ '#', ' ', '#', '#', '#', ' ' ],
[ '#', ' ', ' ', ' ', ' ', '#' ],
[ '#', ' ', ' ', ' ', ' ', '#' ],
[ ' ', '#', ' ', '#', '#', ' ' ],
[ ' ', '#', '#', '#', '#', '#' ],
[ '#', '#', ' ', ' ', '#', ' ' ]
]
arr2Bs = [
[' ', '#', '#', ' ', '#', '#' ],
[ '#', '#', '#', ' ', ' ', ' ' ],
[ ' ', '#', ' ', ' ', '#', '#' ],
[ ' ', ' ', '#', '#', '#', ' ' ],
[ ' ', ' ', '#', '#', '#', ' ' ],
[ ' ', ' ', '#', ' ', '#', ' ' ]
]
2단계. 1단계에서 만든 2차원 배열 arr1Bs, arr2Bs을 비교하여 둘 중 하나 #이 있으면 #으로 아니면 공백으로 바꾸기
앞에서 구한 arr1Bs, arr2Bs를 비교하여
arr1Bs 원소에 #이 있거나 또는 arr2Bs 원소에 #이 있을 경우 #으로 바꾸고 아닐 경우 공백으로 바꾸어주었습니다.
2차원 배열이라 중복 for문을 사용하였고 비교는 삼항연산자를 사용하여 구하였습니다.
// 2단계. 1단계에서 만든 2차원 배열 arr1Bs, arr2Bs을 비교하여 둘 중 하나 #이 있으면 #으로 아니면 공백으로 바꾸기
for(let i=0; i<n; i++){
for(let j=0; j<n; j++){
arr1Bs[i][j] === '#' || arr2Bs[i][j] === '#' ? arr1Bs[i][j] = '#' : arr1Bs[i][j] = ' ';
}
}
삼항 연산자
구문 : 조건 ? true : false
- 조건이 true이면 true를 실행
- 조건이 false이면 false를 실행
arr1Bs[i][j] === '#' || arr2Bs[i][j] === '#' ? arr1Bs[i][j] = '#' : arr1Bs[i][j] = ' ';
- || : 또는
- === : ==보다 더 엄격하게 같음을 비교할 때 사용하는 연산자
혹시 여기서 arr1Bs[i][j]이 잘 이해가 안된다면 밑에 설명을 보시면 됩니다.
arr1Bs = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]] 이면
- arr1Bs[0][1] = '2'
- arr1Bs[1][3] = '9'
테스트 1
n=5; arr1=[9, 20, 28, 18, 11]; arr2=[30, 1, 21, 17, 28];
arr1Bs = [
[ '#', '#', '#', '#', '#' ],
[ '#', ' ', '#', ' ', '#' ],
[ '#', '#', '#', ' ', '#' ],
[ '#', ' ', ' ', '#', '#' ],
[ '#', '#', '#', '#', '#' ]
]
테스트 2
n=6; arr1=[46, 33, 33 ,22, 31, 50]; arr2=[27 ,56, 19, 14, 14, 10];
arr1Bs =[
[ '#', '#', '#', '#', '#', '#' ],
[ '#', '#', '#', ' ', ' ', '#' ],
[ '#', '#', ' ', ' ', '#', '#' ],
[ ' ', '#', '#', '#', '#', ' ' ],
[ ' ', '#', '#', '#', '#', '#' ],
[ '#', '#', '#', ' ', '#', ' ' ]
]
3단계. 2차원 배열을 1차원 배열로 바꾸어주기
마지막으로 2단계에서 나온 2차원 배열을 1차원 배열로 바꾸어주어야 되는데요.
앞에서는 문자열을 여러 개의 문자열로 만들 때는 split()를 사용했는데요.
여기서는 반대로 여러 개의 문자열을 하나로 만들 때는join()을 사용하면 쉽게 바꿀 수 있습니다.
// 3단계. 2차원 배열을 1차원 배열로 바꾸어주기
for(let i=0; i<n; i++){
answer.push(arr1Bs[i].join(''));
}
MDN Web Docs
join() 메서드는 배열의 모든 요소를 연결해 하나의 문자열로 만듭니다.
구문 : arr.join([separator])
- separator Optional
- 배열의 각 요소를 구분할 문자열을 지정합니다.
- 이 구분자는 필요한 경우 문자열로 변환됩니다.
- 생략하면 배열의 요소들이 쉼표로 구분됩니다.
- separator가 빈 문자열이면 모든 요소들이 사이에 아무 문자도 없이 연결됩니다.
// join예제
var a = ['바람', '비', '불'];
var myVar1 = a.join(); // myVar1에 '바람,비,불'을 대입
var myVar2 = a.join(', '); // myVar2에 '바람, 비, 불'을 대입
var myVar3 = a.join(' + '); // myVar3에 '바람 + 비 + 불'을 대입
var myVar4 = a.join(''); // myVar4에 '바람비불'을 대입
테스트 1
n=5; arr1=[9, 20, 28, 18, 11]; arr2=[30, 1, 21, 17, 28];
arr1Bs = [
[ '#', '#', '#', '#', '#' ],
[ '#', ' ', '#', ' ', '#' ],
[ '#', '#', '#', ' ', '#' ],
[ '#', ' ', ' ', '#', '#' ],
[ '#', '#', '#', '#', '#' ]
]
answer.push(arr1Bs[i].join('')); -> answer=["#####","# # #", "### #", "# ##", "#####"]
테스트 2
n=6; arr1=[46, 33, 33 ,22, 31, 50]; arr2=[27 ,56, 19, 14, 14, 10];
arr1Bs =[
[ '#', '#', '#', '#', '#', '#' ],
[ '#', '#', '#', ' ', ' ', '#' ],
[ '#', '#', ' ', ' ', '#', '#' ],
[ ' ', '#', '#', '#', '#', ' ' ],
[ ' ', '#', '#', '#', '#', '#' ],
[ '#', '#', '#', ' ', '#', ' ' ]
]
answer.push(arr1Bs[i].join('')); -> answer=["######", "### #", "## ##", " #### ", " #####", "### # "]
여기까지 프로그래머스 비밀지도 해결방안에 대해 설명해보았습니다.