문제
풀이에 앞서.. 어떻게 입력을 받아야 하는가?
백준에서 자바스크립트로 문제를 풀기 위해서는 입출력에 대한 인터페이스를 사용자가 직접 정의해야 한다.
입력을 받는 방법에는 두 가지 방법이 자주 쓰인다.
첫번째 방법
// 한 줄의 입력만 받을 때
var fs = require('fs');
var input = fs.readFileSync('/dev/stdin').toString().split(' '); // 공백으로 입력을 구분한다.
// 여러 줄의 입력을 받을 때
var fs = require('fs');
var input = fs.readFileSync('/dev/stdin').toString().split('\n'); // 개행문자로 입력을 구분한다.
두번째 방법
// 한 줄의 입력만 받을 때
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on("line", function(line) {
console.log("hello !", line); // 다음의 line에서 입력을 받는다.
rl.close();
}).on("close", function() {
// 수행할 작업을 구현하기
process.exit();
});
// 여러 줄의 입력을 받을 때
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on('line', function (line) {
input.push(line) // input 배열에 입력을 한 줄씩 넣어준다.
})
.on('close', function () {
sol(input); // 입력이 포함된 input 배열을 구현한 sol함수에 인수로 넣을 수 있다.
process.exit();
});
다음 중 마음에 드는 방법으로 입력을 받으면 되겠다.
사실 첫번째 방법은 이유 모를 오류가 생기는 경우가 있어, 글쓴이는 두번째 방법을 계속 이용하는 중이다.
문제 풀이
처음에는 첫번째 방법을 사용해서 문제를 풀어보다 도저히 풀리지 않아서
두번째 방법도 있다는 것을 알게 되어 다시 풀었다.
수많은 실패 끝에 결국 성공해서, 나와 같은 경험을 하는 사람들을 위해 글로 정리하여 기쁨을 나누고 싶었다.
계속 실패하는게 답답해서 열심히 검색해서 답을 찾아보려고 했는데, 자료도 거의 없어서 속상했다.
아무래도 백준저지에서는 JavaScript 사용이 만만치 않아 그런 듯 하다.
아무튼, 처음 문제를 푼 방법은 다음과 같다.
const stack = [];
let top = 0;
let answer = "";
const cmdObj = {
push: function (x) {
stack[top] = x;
top++;
},
pop: function () {
if (top > 0) {
top--;
return stack.splice(-1);
} else return -1;
},
size: function () {
return top;
},
empty: function () {
if (top === 0) return 1;
else return 0;
},
top: function () {
if (top > 0) return stack[top - 1];
else return -1;
},
};
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let input = [];
rl.on("line", function (line) {
input.push(line);
}).on("close", function () {
input.map((line) => {
const cmd = line.split(" ");
if (cmd[0] === "push") {
cmdObj[cmd[0]](parseInt(cmd[1]));
} else if (
cmd[0] === "pop" ||
cmd[0] === "size" ||
cmd[0] === "empty" ||
cmd[0] === "top"
)
answer += cmdObj[cmd[0]]() + "\n";
});
console.log(answer);
process.exit();
});
각 명령을 수행할 때 마다 출력을 해줬을 때는, 시간초과 이슈가 있었다.
그리하여 모든 출력을 하나의 변수에 담아 한 번에 출력하기 위해 answer 변수를 선언했다.
스택 자료구조를 사용해야 하므로, stack 배열과 stack의 top 변수를 선언했다.
push, pop, size, empty, top 명령을 실행하기 위해 cmdObj를 정의했다.
cmdObj 안에는 key:value
형태로 명령 : 실행할 함수
를 정의 했으므로,
pop 명령을 cmdObj"pop" 으로 수행할 수 있다.
입력을 처리하는 두번째 방법을 이용해서, input 배열에 각 명령들을 담아준다.
push 명령은 push 1
과 같이 뒤에 스택에 넣을 숫자가 같이 나오므로,
split(" ")을 이용해 명령과 숫자를 분리하도록 했다.
"push 1"
의 경우 cmd=["push", "1"]"pop"
의 경우 cmd=["pop"] 의 결과가 나온다.
다음 if문에서 cmd의 0번 인덱스가 push일 때는 숫자로 타입변환한 숫자를 넣어주고,
pop, size, empty, top 일 때는 리턴값에 개행문자(\n)을 붙여서 정답 문자열에 더해준다.
결국 어찌저찌 해서 테스트에 통과하기는 했다.
우선 통과하는 것을 목표로 코드를 작성하느라 코드가 난잡해 보였던 것도 있고,
이 기회에 ES6 문법도 복습해볼 겸 해서 코드를 수정해봤다.
수정한 코드
const stack = [];
let top = 0;
let answer = "";
const cmdObj = {
push: (x) => (stack[top++] = x), // 1. arrow function
pop: () => {
if (top) {
top--;
return stack.splice(-1);
} else return -1;
},
size: () => top,
empty: () => (!top ? 1 : 0),
top: () => (top ? stack[top - 1] : -1), // 2. 삼항 조건 연산자
};
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let input = [];
rl.on("line", (line) => input.push(line)).on("close", () => {
input.map((line, idx) => { // 3. map함수의 두번째 인자
if (idx === 0) return;
const [cmd, num] = line.split(" "); // 4. 구조분해할당
if (cmd === "push") {
cmdObj[cmd](parseInt(num));
} else answer += `${cmdObj[cmd]()}\n`; // 5. 템플릿리터럴
});
console.log(answer);
process.exit();
});
설명은 위에서 열심히 적어놨고 동일하게 작동한다.
모르는 부분은 이전 코드와 비교해보면 될 것 같다.
적용한 문법은 다음과 같다.
모르는 부분은 해당 개념을 눌러서 공부해보면 좋을 듯 하다.
포스팅 이후 추가 내용 6.19(토)
입력을 받는 부분과 문제를 푸는 부분을 뚜렷하게 분리하는 편이 더 가독성이 좋다.
2번째 코드를 그대로 가져와 작성했다.
최종 코드
// 입력을 인자로 받아 문제를 푸는 solution 함수
function solution(input) {
const stack = [];
let top = 0;
let answer = "";
const cmdObj = {
push: (x) => (stack[top++] = x),
pop: () => {
if (top) {
top--;
return stack.splice(-1);
}
return -1;
},
size: () => top,
empty: () => (!top ? 1 : 0),
top: () => (top ? stack[top - 1] : -1),
};
input.slice(1).map((str) => {
const [cmd, num] = str.split(" ");
if (cmd === "push") cmdObj[cmd](+num);
else answer += `${cmdObj[cmd]()}\n`;
});
return answer;
}
// 아래는 백준에서 여러 줄의 입력을 받는 부분이다.
const input = [];
require("readline")
.createInterface(process.stdin, process.stdout)
.on("line", (line) => {
input.push(line);
})
.on("close", () => {
console.log(solution(input)); // 이 부분에서 함수를 실행하고 정답을 출력한다.
process.exit();
});
'DS & Algorithm > baekjoon' 카테고리의 다른 글
[백준] 13023번 ABCDE - JavaScript(NodeJS) (0) | 2021.05.27 |
---|---|
[백준] 1932번 정수삼각형 - JavaScript(NodeJS) (0) | 2021.05.17 |
[백준] 1309번 동물원 - JavasScript(NodeJS) (0) | 2021.05.16 |
[백준] 1406번 에디터 - JavaScript(NodeJS) (2) | 2021.05.02 |
[백준] 9093번 단어 뒤집기 - JavaScript(NodeJS) (0) | 2021.05.01 |