[백준] 4779 칸토어 집합 JavaScript

·2024년 5월 27일

문제

칸토어 집합은 0과 1사이의 실수로 이루어진 집합으로, 구간 [0, 1]에서 시작해서 각 구간을 3등분하여 가운데 구간을 반복적으로 제외하는 방식으로 만든다.

전체 집합이 유한이라고 가정하고, 다음과 같은 과정을 통해서 칸토어 집합의 근사를 만들어보자.

  1. -가 3N개 있는 문자열에서 시작한다.

  2. 문자열을 3등분 한 뒤, 가운데 문자열을 공백으로 바꾼다. 이렇게 하면, 선(문자열) 2개가 남는다.

  3. 이제 각 선(문자열)을 3등분 하고, 가운데 문자열을 공백으로 바꾼다. 이 과정은 모든 선의 길이가 1일때 까지 계속 한다.

예를 들어, N=3인 경우, 길이가 27인 문자열로 시작한다.

---------------------------
여기서 가운데 문자열을 공백으로 바꾼다.

--------- ---------
남은 두 선의 가운데 문자열을 공백으로 바꾼다.

--- --- --- ---
한번 더

- - - - - - - -
모든 선의 길이가 1이면 멈춘다. N이 주어졌을 때, 마지막 과정이 끝난 후 결과를 출력하는 프로그램을 작성하시오.

입력

입력을 여러 줄로 이루어져 있다. 각 줄에 N이 주어진다. 파일의 끝에서 입력을 멈춘다. N은 0보다 크거나 같고, 12보다 작거나 같은 정수이다.

출력

입력으로 주어진 N에 대해서, 해당하는 칸토어 집합의 근사를 출력한다.

예제 입력

0
1
3
2

예제 출력

-
- -
- - - - - - - -
- - - -

내가 했던 풀이 방법

  1. 3^N을 계산하여 n에 저장해주고, 길이가 n인 배열을 만들고, 모든 요소를 "-"로 채워준다. (문자열이 계속 공백으로 바뀌어야 하기 때문에 불변한 문자열보다 배열로 사용하는 것이 구현에 더 편하다.)
  2. n이 1일 경우, 그대로 출력하고, 1이 아닐 경우 while문(3~5번)을 n이 1이 될 때까지 반복한다.
  3. 0부터 string.length까지 j를 n만큼씩 증가시켜준다. 이때, string[j]가 "-"일 경우에만 다음 연산을 진행한다. (여기서 사용하는 j는 문자열을 "-"와 " "을 나누었을 때 덩어리의 첫 index를 의미한다. 예를 들어 -- --일 경우에는 "--", "  ", "--"의 덩어리가 있게 되고, j는 0, 2, 4가 된다.)
  4. k가 j+n/3부터 j+2*(n/3)전까지 k를 1씩 증가시키면서 string[k]를 " "으로 바꿔준다. (해당 덩어리의 가운데를 공백으로 바꿔주어야 하기 때문이다. 그러므로, j에서 현재 길이(n)을 3등분한 값을 더해준 위치부터 3등분한 길이만큼까지를 공백으로 바꾸어주어야 한다.)
  5. 연산이 끝난 뒤, n을 3으로 나눠준 뒤, 3번부터 다시 반복한다.
  6. 모든 반복이 끝난 뒤, string을 문자열로 변환해준다.
  7. 해당 연산을 입력받은 N의 개수만큼 반복해준다.

코드

const fs = require('fs');
let N = fs.readFileSync(0, 'utf-8').toString().trim().split('\n');

for (let i = 0; i < N.length; i++) {
  let n = Number(N[i].trim());
  n = 3 ** n;
  let string = Array.from({ length: n }, () => '-');
  if (n !== 1) {
    while (true) {
      if (n === 1) break;
      for (let j = 0; j < string.length; j += n) {
        if (string[j] === '-') {
          for (let k = j + n / 3; k < j + 2 * (n / 3); k++) {
            string[k] = ' ';
          }
        } else continue;
      }
      n /= 3;
    }
  }
  console.log(string.join(''));
}

회고

직전에 풀었던 문제랑 비슷한 문제였는데, 조금 더 복잡해진? 문제이다. 아무래도 이전 문제는 배열을 그냥 합쳐주기만 하면 됐는데 이번에는 중간에 연산을 생략해야하는 범위가 나오고 그 길이도 제각각이다보니 다음 연산을 수행해주어야 할 위치를 찾기를 어떻게 구현해야할지 생각하다보니 더 복잡하게 생각한 것 같다.

profile
Frontend🍓

0개의 댓글