JS로 백준 문제 풀기: 입력 처리 완벽? 가이드

윤뿔소·2025년 1월 23일
0

Algorithm / Design

목록 보기
2/15
post-thumbnail

백준 문제를 JS로 풀면서 가장 먼저 마주치는 난관은 입력 처리입니다. 프로그래머스와 달리 백준은 표준 입출력(stdin/stdout) 방식을 사용하는데, 이는 브라우저 환경에 최적화된 JS의 특성과 잘 맞지 않습니다.

💢 백준을 자바스크립트로 풀기 어려운 이유

코딩 문제를 해결하는 대표적인 사이트들인 백준, 프로그래머스, LeetCode, 구름 등이 있습니다.

그 중 프로그래머스는 아래 코드와 같이 입력받는 값이 함수의 매개변수로 주어지기 때문에 입력받는 부분을 따로 만들 필요가 없습니다.

function solution(age) {
  var answer = 0;
  return answer;
}

하지만 백준은 입출력을 stdin, stdout 방식으로 받기 때문에 입출력 과정을 전부 명시해줘야 합니다.

그래서 여타 다른 언어들처럼 node.js를 사용합니다.

1. 입력의 어려움

node.js 덕분에 입력을 처리할 방법이 생겼지만 브라우저의 이벤트를 처리하는 언어로써 입출력이 C++, python에 비해 직관적이지 않고 복잡합니다.

2. 시간 초과, 메모리 초과

인터프리터 언어인 js는 컴파일 언어인 c, c++ 보다 시간이 오래 걸리기 때문에 시간제한을 빡빡하게 걸어놓은 문제는 해결하지 못하는 경우가 있습니다.

🔄 fs 입력 데이터 원하는 형태로 가공하기

주로 쓰이는 함수

함수설명
.toString()입력데이터를 문자열로 바꾸어줌
.trim()문자열 앞뒤 공백(space, tab, \n) 제거
.split(특정 문자)특정 문자 기준으로 나누고 각 부분을 요소로 가지는 배열 생성

1. 한 개 입력 : a

가공 전 입력 데이터가공 후(input)
a'a'
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';

const input = fs.readFileSync(filePath).toString().trim();

2. 한 줄 : a b c

가공 전 입력 데이터가공 후 (input)
a b cinput = ['a', 'b', 'c']
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';

const input = fs.readFileSync(filePath).toString().trim().split(' ');

3. 여러 줄 입력 : a<br>b

가공 전 입력 데이터가공 후(input)
a
b
input = ['a', 'b']
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';

const input = fs.readFileSync(filePath).toString().trim().split('\n');

4. 한 글자(N) + 한 줄 : 3<br>a b c

가공 전 입력 데이터가공 후(n, input)
3
a b c
n = 3
arr = ['a', 'b', 'c']
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';

const input = fs.readFileSync(filePath).toString().trim().split('\n');
const n = parseInt(input[0]); // 첫 번째 줄은 숫자 n으로 저장
const arr = input[1].split(' ');

5. 한 글자(N) + 여러 줄 : 3<br>a<br>b<br>c

가공 전 입력 데이터가공 후(n, input)
3
a
b
c
n = 3
arr = ['a', 'b', 'c']
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';

const input = fs.readFileSync(filePath).toString().trim().split('\n');
const n = +input[0]; // 단항 플러스 연산자(+): 숫자로 바꿈 or +(input[0])
const arr = input.slice(1).map((line) => line.split(' '));

입력받은 데이터를 숫자로 변환해야 하는 경우는 map(Number), map(el => +el) 등을 사용해야 합니다.

주의사항

  1. 형변환 확인 : 입력값이 숫자여야 할 경우 반드시 Number() 또는 parseInt()로 변환 필수!
  2. 공백 처리 : 입력의 시작이나 끝에 있는 공백을 제거하기 위해 trim()을 사용
  3. 메모리 관리 : 대용량 입력의 경우 한 번에 모든 데이터를 배열로 변환하는 것보다 필요한 만큼만 처리하는 것이 효율적

🔄 readline 모듈로 백준 문제 풀기

readline 모듈은 Node.js에서 제공하는 또 다른 입력 처리 방식입니다. fs 모듈과 달리 대화형(interactive) 방식으로 입력을 처리하며, 한 줄씩 읽어들이는 특징이 있습니다.

readline 모듈의 기본 설정

먼저 모듈을 초기화하는 방법을 알아보겠습니다:

const readline = require('readline');
const rl = readline.createInterface({
  input: process.stdin, // 표준 입력 스트림 사용
  output: process.stdout, // 표준 출력 스트림 사용
});

입력 패턴별 처리 방법

1. 단일 라인 입력

입력 데이터처리 결과
Hello world!Hello world!
const readline = require('readline');
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

// 한 줄 입력 받기
rl.on('line', function (line) {
  console.log(line); // 입력된 라인 처리
  rl.close(); // 입력 종료
}).on('close', function () {
  process.exit(); // 프로그램 종료
});

2. 멀티라인 입력 처리

입력 데이터처리 결과
3
a b c
d e f
x y z
n = 3
[['a', 'b', 'c'], ['d', 'e', 'f'], ['x', 'y', 'z']]
const readline = require('readline');
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

let n; // 입력 받을 줄 수
const arr = []; // 입력 데이터를 저장할 배열

rl.on('line', (line) => {
  if (!n) {
    // 첫 줄: 입력 받을 줄 수 저장
    n = parseInt(line);
  } else {
    // 이후 줄: 공백으로 분리하여 배열에 저장
    arr.push(line.split(' '));

    // 입력이 완료되면 종료
    if (arr.length === n) {
      rl.close();
    }
  }
});

readline 🆚 fs 모듈 비교

특징readlinefs
입력 방식대화형, 스트림 기반파일 기반, 일괄 처리
처리 속도상대적으로 느림빠름
메모리 사용효율적 (한 줄씩 처리)전체 파일을 한번에 로드
코드 복잡도비동기 처리로 다소 복잡간단하고 직관적

readline 모듈은 대화형 프로그램이나 실시간 입력이 필요한 경우에 유용하지만, 백준과 같은 알고리즘 문제 풀이에서는 fs 모듈이 더 효율적입니다. 실행 속도가 중요한 문제에서는 fs 모듈을 우선적으로 고려하시기를 추천드립니다.

참고로 readline의 이벤트 기반 처리는 비동기적으로 동작하기 때문에, 복잡한 입력 처리가 필요한 경우 코드가 다소 복잡해질 수 있다는 점을 염두에 두시기 바랍니다.

참고

profile
코뿔소처럼 저돌적으로

0개의 댓글