jiho_bae
Go devlog
jiho_bae
전체 방문자
오늘
어제
  • 분류 전체보기 (158)
    • JavaScript (38)
      • theory (34)
      • vanilla (4)
    • HTML & CSS (2)
    • Browser (3)
    • CS (6)
      • linux (1)
      • shell (2)
      • compiler (2)
    • DS & Algorithm (87)
      • theory (5)
      • basic (7)
      • programmers (30)
      • baekjoon (45)
    • Design Pattern (2)
    • Error (4)
    • Git & Github (4)
    • Tools (1)
    • 부트캠프 (4)
    • Small Tips (2)
    • Java (3)
    • test (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 백준 자바스크립트 입력 템플릿
  • 자바스크립트 sort는 왜 그모양일까
  • 자바스크립트 모듈 시스템
  • 억억단을 외우자 javascript
  • 13460 javascript nodejs
  • 병합정렬 자바스크립트
  • 자바스크립트 이벤트 위임
  • 덧칠하기 javascript
  • 자바스크립트 배열의 특수함
  • 리코쳇 로봇 javascript
  • safari Date format NaN
  • JavaScript
  • 백준 17406 nodeJS
  • fetch 취소하기
  • 깃 이전 커밋에서 새 브랜치 만들기
  • 외벽 점검 javascript
  • 카카오 코딩테스트 양궁대회 nodeJS
  • 프로그래머스 숫자카드나누기 javascript
  • 퀵정렬 자바스크립트
  • 25632 소수 부르기 게임
  • 가사 검색 자바스크립트
  • javascript use strict
  • 자바스크립트 채팅방 스크롤
  • 리액트 프로젝트 디버깅하기
  • safari invalid date error
  • 자바스크립트 비동기 마이크로 태스크 큐와 렌더링 과정
  • 계수정렬 자바스크립트
  • 대충만든자판 javascript
  • 자바스크립트 커링
  • 1753 최단경로 javascript

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
jiho_bae

Go devlog

[백준] 10828번 스택 - JavaScript(NodeJS)
DS & Algorithm/baekjoon

[백준] 10828번 스택 - JavaScript(NodeJS)

2021. 5. 1. 03:01

문제

 

10828번: 스택

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net

스택 자료구조

 


풀이에 앞서.. 어떻게 입력을 받아야 하는가?

 

백준에서 자바스크립트로 문제를 풀기 위해서는 입출력에 대한 인터페이스를 사용자가 직접 정의해야 한다.

 

입력을 받는 방법에는 두 가지 방법이 자주 쓰인다.

 

첫번째 방법

// 한 줄의 입력만 받을 때
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();
});

설명은 위에서 열심히 적어놨고 동일하게 작동한다.

모르는 부분은 이전 코드와 비교해보면 될 것 같다.

 

적용한 문법은 다음과 같다.

  1. arrow function
  2. 삼항 조건 연산자
  3. map 함수의 2번째 인자
  4. 구조분해할당
  5. 템플릿리터럴

모르는 부분은 해당 개념을 눌러서 공부해보면 좋을 듯 하다.

 

실행 결과

 

 

포스팅 이후 추가 내용 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
    'DS & Algorithm/baekjoon' 카테고리의 다른 글
    • [백준] 1932번 정수삼각형 - JavaScript(NodeJS)
    • [백준] 1309번 동물원 - JavasScript(NodeJS)
    • [백준] 1406번 에디터 - JavaScript(NodeJS)
    • [백준] 9093번 단어 뒤집기 - JavaScript(NodeJS)
    jiho_bae
    jiho_bae
    하루에 한 걸음씩

    티스토리툴바