코딩/프로그래머스 코딩테스트

[프로그래머스] 비밀지도

민쯔 2021. 12. 8. 02:43
728x90
반응형

안녕하세요. 민쯔입니다.😊
정말 오랜만이죠???
제가 과제와 시험공부하다 보니까 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가 있고 이 두 지도를 겹쳤을 때 나오는 값을 구하는 문제입니다.

문제 순서

  1. arr1, arr2에 들어있는 숫자(10진수)를 2진수를 바꾸기
  2. 2진수로 바꾼 arr1, arr2의 값을 1이면 # 0이면 공백으로 바꾸기
  3. 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에 넣어주면 끝~!!

728x90
반응형