안녕하세요. 민쯔입니다.😊
정말 오랜만이죠???
제가 과제와 시험공부하다 보니까 3주가 지나 있더라고요ㅠㅠ
이제 다시 프로그래머스 열심히 풀어야겠어요!!
이번에는 비밀지도에 대해 풀어봤는데,
뭔가 제가 쓴 코드가 허튼짓 하는 느낌이 들지만
그래도 해결방안에 대해 설명해보겠습니다.
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가 있고 이 두 지도를 겹쳤을 때 나오는 값을 구하는 문제입니다.
문제 순서
- arr1, arr2에 들어있는 숫자(10진수)를 2진수를 바꾸기
- 2진수로 바꾼 arr1, arr2의 값을 1이면 # 0이면 공백으로 바꾸기
- arr1와 arr2를 비교하여 둘 중 하나 #이 있으면 #으로 아니면 공백으로 바꾸기
arr1, arr2의 숫자를 2진법으로 만들고 #, 공백으로 교체하기
// 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);
}
10진수를 2진수로
arr1[i].toString(2).padStart(n,0)를 사용하면 쉽게 10진법을 2진법으로 바꿀 수 있습니다.
물론 여기서 arr1[i].toString(2);만 해도 충분히 2진법으로 바꿀 수 있지만
이렇게 쓸 경우 9이면 01001로 바뀌어야 되는데 1001만 나옵니다.
그래서 padStart(n,0)를 써야 됩니다.
- padStart() 메서드는 현재 문자열의 시작을 다른 문자열로 채워, 주어진 길이를 만족하는 새로운 문자열을 반환합니다. 채워 넣기는 대상 문자열의 시작(좌측)부터 적용됩니다.
- padStart(n,0) : 문자열의 길이가 n보다 작을 경우 문자열 앞쪽에 0을 채워주어라
- n이 5이고, 바꾸야 되는 숫자가 9일 경우(9가 2진수로 바꾸면 1001)
- 01001
이렇게 n자릿수 2진수를 만들었습니다.
2진수를 1을 #으로 0을 공백으로 표시하기
2진수를 1을 #으로 0을 공백으로 표시해야 되는데 정규식을 활용해서 구하였습니다.
사실 원래 for문을 사용해서 했지만...ㅋ
다른 사람 풀이 보기에서 다들 정규식을 사용했더라고요.
이 쉬운 방법을 왜 생각을 못했는지!!!!
앞에서 arr1[i].toString(2).padStart(n,0)까지 썼는데(10진수를 2진수로)
그 뒤에 .replace(/0/g,' ').replace(/1/g,'#')를 썼습니다.
여기서 굳이 정규식을 쓴 이유는 바꿔야 되는 게(0,1) 문자열이 아닌 숫자여서 그런지
replace(0, '#') 쓰면 답이 이상하게 나오더라고요😥
- replace() 메서드는 어떤 패턴에 일치하는 일부 또는 모든 부분이 교체된 새로운 문자열을 반환합니다. 그 패턴은 문자열이나 정규식이 될 수 있으며, 교체 문자열은 문자열이나 모든 매치에 대해서 호출된 함수일 수 있습니다.
- p.replace('dog', 'monkey') : 문자열 p에서 dog를 monkey로 바꾸어라
- replace(/0/g,' ') : 0을 공백으로
- replace(/1/g,'#') : 1을 #으로
- g : 전체 매칭
그리고 split('')를 쓴 이유는 나중에 뒤에서 arr1, arr2를 비교해야 되는데
각각 비교하려면 합쳐진 문자열보다는 각각의 배열의 원소로 담겨 있는 게 비교하기 편하더라고요.
- split() 메서드는 String 객체를 지정한 구분자를 이용하여 여러 개의 문자열로 나눕니다.
- split('') : 01001 -> '0' '1' '0' '0' '1'
각각 arr1Bs, arr2Bs에 담아주었습니다.
테스트 1에서의 arr1Bs, arr2Bs
console.log(arr1Bs);
[
[ ' ', '#', ' ', ' ', '#' ],
[ '#', ' ', '#', ' ', ' ' ],
[ '#', '#', '#', ' ', ' ' ],
[ '#', ' ', ' ', '#', ' ' ],
[ ' ', '#', ' ', '#', '#' ]
]
console.log(arr2Bs);
[
[ '#', '#', '#', '#', ' ' ],
[ ' ', ' ', ' ', ' ', '#' ],
[ '#', ' ', '#', ' ', '#' ],
[ '#', ' ', ' ', ' ', '#' ],
[ '#', '#', '#', ' ', ' ' ]
]
이와 같이 2차원 배열로 나옵니다.
두 장의 지도를 겹쳤을 때
// 두 장의 지도를 겹쳤을 때
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] = ' ';
}
}
앞서 구한 arr1Bs, arr2Bs를 비교하여
arr1Bs 원소에 #이 있거나 또는 arr2Bs 원소에 #이 있을 경우
#으로 바꾸고
아닐 경우 공백으로 바꾸어주었습니다.
2차원 배열이라 중복 for문을 사용하였고 비교는 삼항연산자를 사용하여 구하였습니다.
- 삼항연산자 : 조건 ? true : false
테스트 1에서의 arr1Bs
console.log(arr1Bs);
[
[ '#', '#', '#', '#', '#' ],
[ '#', ' ', '#', ' ', '#' ],
[ '#', '#', '#', ' ', '#' ],
[ '#', ' ', ' ', '#', '#' ],
[ '#', '#', '#', '#', '#' ]
]
2차원 배열을 1차원 배열로
// 2차원배열을 1차원 배열로
for(let i=0; i<n; i++){
answer.push(arr1Bs[i].join(''));
}
마지막으로 2차원 배열을 1차원 배열로 바꾸면 되는데
앞에서는 문자열을 여러 개의 문자열로 만들 때는 split()를 사용했는데요.
여기서는 반대로 여러개의 문자열을 하나로 만들때는 join()을 사용하면 쉽게 바꿀 수 있습니다.
- join() 메서드는 배열의 모든 요소를 연결해 하나의 문자열로 만듭니다.
- a = [ '#', '#', '#', '#', '#' ] 이면
- a.join() : "#,#,#,#,#"
- a.join('') : "#####"
이 값을 answer에 넣어주면 끝~!!
'코딩 > 프로그래머스 코딩테스트' 카테고리의 다른 글
[프로그래머스] 같은 숫자는 싫어 (0) | 2021.12.28 |
---|---|
[프로그래머스] 가운데 글자 가져오기 (0) | 2021.12.09 |
[프로그래머스] 나머지가 1이 되는 수 찾기 (0) | 2021.11.20 |
[프로그래머스] 부족한 금액 계산하기 (0) | 2021.11.11 |
[프로그래머스] 최소직사각형 (0) | 2021.11.09 |