백준 문제를 JS로 풀면서 가장 먼저 마주치는 난관은 입력 처리입니다. 프로그래머스와 달리 백준은 표준 입출력(stdin
/stdout
) 방식을 사용하는데, 이는 브라우저 환경에 최적화된 JS의 특성과 잘 맞지 않습니다.
코딩 문제를 해결하는 대표적인 사이트들인 백준, 프로그래머스, LeetCode, 구름 등이 있습니다.
그 중 프로그래머스는 아래 코드와 같이 입력받는 값이 함수의 매개변수로 주어지기 때문에 입력받는 부분을 따로 만들 필요가 없습니다.
function solution(age) {
var answer = 0;
return answer;
}
하지만 백준은 입출력을 stdin
, stdout
방식으로 받기 때문에 입출력 과정을 전부 명시해줘야 합니다.
그래서 여타 다른 언어들처럼 node.js를 사용합니다.
node.js 덕분에 입력을 처리할 방법이 생겼지만 브라우저의 이벤트를 처리하는 언어로써 입출력이 C++, python에 비해 직관적이지 않고 복잡합니다.
인터프리터 언어인 js는 컴파일 언어인 c, c++ 보다 시간이 오래 걸리기 때문에 시간제한을 빡빡하게 걸어놓은 문제는 해결하지 못하는 경우가 있습니다.
fs
입력 데이터 원하는 형태로 가공하기함수 | 설명 |
---|---|
.toString() | 입력데이터를 문자열로 바꾸어줌 |
.trim() | 문자열 앞뒤 공백(space, tab, \n) 제거 |
.split(특정 문자) | 특정 문자 기준으로 나누고 각 부분을 요소로 가지는 배열 생성 |
a
가공 전 입력 데이터 | 가공 후(input) |
---|---|
a | 'a' |
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';
const input = fs.readFileSync(filePath).toString().trim();
a b c
가공 전 입력 데이터 | 가공 후 (input) |
---|---|
a b c | input = ['a', 'b', 'c'] |
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';
const input = fs.readFileSync(filePath).toString().trim().split(' ');
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');
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(' ');
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)
등을 사용해야 합니다.
Number()
또는 parseInt()
로 변환 필수!trim()
을 사용readline
모듈로 백준 문제 풀기readline
모듈은 Node.js에서 제공하는 또 다른 입력 처리 방식입니다. fs
모듈과 달리 대화형(interactive) 방식으로 입력을 처리하며, 한 줄씩 읽어들이는 특징이 있습니다.
먼저 모듈을 초기화하는 방법을 알아보겠습니다:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin, // 표준 입력 스트림 사용
output: process.stdout, // 표준 출력 스트림 사용
});
입력 데이터 | 처리 결과 |
---|---|
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(); // 프로그램 종료
});
입력 데이터 | 처리 결과 |
---|---|
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
모듈 비교특징 | readline | fs |
---|---|---|
입력 방식 | 대화형, 스트림 기반 | 파일 기반, 일괄 처리 |
처리 속도 | 상대적으로 느림 | 빠름 |
메모리 사용 | 효율적 (한 줄씩 처리) | 전체 파일을 한번에 로드 |
코드 복잡도 | 비동기 처리로 다소 복잡 | 간단하고 직관적 |
readline
모듈은 대화형 프로그램이나 실시간 입력이 필요한 경우에 유용하지만, 백준과 같은 알고리즘 문제 풀이에서는 fs
모듈이 더 효율적입니다. 실행 속도가 중요한 문제에서는 fs
모듈을 우선적으로 고려하시기를 추천드립니다.
참고로 readline
의 이벤트 기반 처리는 비동기적으로 동작하기 때문에, 복잡한 입력 처리가 필요한 경우 코드가 다소 복잡해질 수 있다는 점을 염두에 두시기 바랍니다.