Lv1. 비밀지도

정현승·2024년 11월 29일

https://school.programmers.co.kr/learn/courses/30/lessons/17681

문제

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.

  1. 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류로 이루어져 있다.
  2. 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 "지도 1"과 "지도 2"라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
  3. "지도 1"과 "지도 2"는 각각 정수 배열로 암호화되어 있다.
  4. 암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.

정답 코드

function solution(n, arr1, arr2) {
  const map1 = arr1.map((num) => num.toString(2).padStart(n, "0"));
  const map2 = arr2.map((num) => num.toString(2).padStart(n, "0"));
  const res = [];
  for (let i = 0; i < n; i++) {
    let row = "";
    for (let j = 0; j < n; j++) {
      if (map1[i][j] === "0" && map2[i][j] === "0") row += " ";
      else row += "#";
    }
    res.push(row);
  }
  return res;
}

문제 해설

  1. 숫자 배열을 이진법 배열로 바꾼다. [1001, 10100, 11100, 10010, 1011] , [11110, 1, 10101, 10001, 11100]
    이 때, 배열의 요소는 숫자가 아닌 문자열

  2. 한 변의 길이가 n인 정사각형 형태로 나타내야 하므로 2진법으로 바꾼 후 padStart로 앞의 빈자리를 0으로 채운다.
    [01001, 10100, 11100, 10010, 01011] , [11110, 00001, 10101, 10001, 11100]

  3. 같은 형태의 배열을 만들어야 하므로 이중 for문을 사용해서 만든다.

  4. 첫 번째 반복문에서는 row 문자열을 초기화해준다.

  5. 두 번째 반복문에서는 map1의 요소와 map2의 요소가 둘 다 0이라면 공백, 둘 중 하나라도 1이라면 #으로 채운다.

  6. 반복문이 끝나기 전에 res 배열에 push 해준다.

toString

const num = 255;
console.log(num.toString());    // 기본값은 10진수: "255"
console.log(num.toString(2));  // 2진수: "11111111"
console.log(num.toString(8));  // 8진수: "377"
console.log(num.toString(16)); // 16진수: "ff"

작동 과정

  1. 입력값 확인
    toString(2)가 호출된 숫자가 무엇인지 확인합니다.
    toString()은 내부적으로 숫자를 이진법 표현으로 변환할 준비를 합니다.

  2. 진법 변환
    숫자는 메모리 내부에서 이진법으로 저장됩니다.
    따라서, toString(2)를 호출하면 이 저장된 이진수를 사람이 읽을 수 있는 문자열 형식의 이진법으로 변환합니다.
    정수와 소수부를 처리하는 방식이 다릅니다:
    정수는 반복적으로 나눗셈의 나머지를 통해 이진수로 변환됩니다.
    소수는 곱셈의 정수 부분을 반복적으로 계산하여 이진수로 변환됩니다.

  3. 문자열 반환
    변환된 이진수를 문자열로 반환합니다.

정수의 변환 과정

숫자에서 정수 부분의 이진법 변환은 반복적으로 2로 나누고 나머지를 기록하는 방식으로 작동합니다.

나눗셈나머지
42 ÷ 2 = 21210
21 ÷ 2 = 10101
10 ÷ 2 = 550
5 ÷ 2 = 221
2 ÷ 2 = 110
1 ÷ 2 = 001

몫이 0이 될 때 까지 2로 나눈 후, 나머지를 역순으로 해서 101010

소수의 변환 과정

소수의 경우, 반복적으로 2를 곱한 정수 부분을 기록합니다.

곱셈결과정수 부분
0.625 × 2 = 1.251.251
0.25 × 2 = 0.50.50
0.5 × 2 = 1.01.01

한계와 주의사항

소수점 이진 표현의 무한 반복

  • 일부 소수는 2진법에서 유한소수가 아닌 무한소수로 표현됩니다.
  • 예: 0.1은 2진법으로 정확히 표현할 수 없고, 반복되는 패턴(0.000110011...)을 가집니다.
  • JavaScript는 부동소수점 표기법(IEEE 754)을 사용하여 근사치를 계산합니다.

값의 오차

  • 매우 작은 소수나 매우 큰 숫자는 toString(2)로 변환 시 정확도가 떨어질 수 있습니다.
  • 이로 인해 소수점 자리에서 예상하지 못한 결과가 나타날 수 있습니다.

0개의 댓글