너무너무 멋져 눈이눈이 부셔

[JS]10799 쇠막대기 백준 자바스크립트 node.js 본문

멋있는 JavaScript

[JS]10799 쇠막대기 백준 자바스크립트 node.js

강하다이녀석 2024. 2. 25. 18:01

문제

여러 개의 쇠막대기를 레이저로 절단하려고 한다. 효율적인 작업을 위해서 쇠막대기를 아래에서 위로 겹쳐 놓고, 레이저를 위에서 수직으로 발사하여 쇠막대기들을 자른다. 쇠막대기와 레이저의 배치는 다음 조건을 만족한다.

  • 쇠막대기는 자신보다 긴 쇠막대기 위에만 놓일 수 있다. - 쇠막대기를 다른 쇠막대기 위에 놓는 경우 완전히 포함되도록 놓되, 끝점은 겹치지 않도록 놓는다.
  • 각 쇠막대기를 자르는 레이저는 적어도 하나 존재한다.
  • 레이저는 어떤 쇠막대기의 양 끝점과도 겹치지 않는다.

아래 그림은 위 조건을 만족하는 예를 보여준다. 수평으로 그려진 굵은 실선은 쇠막대기이고, 점은 레이저의 위치, 수직으로 그려진 점선 화살표는 레이저의 발사 방향이다.

이러한 레이저와 쇠막대기의 배치는 다음과 같이 괄호를 이용하여 왼쪽부터 순서대로 표현할 수 있다.

  1. 레이저는 여는 괄호와 닫는 괄호의 인접한 쌍 ‘( ) ’ 으로 표현된다. 또한, 모든 ‘( ) ’는 반드시 레이저를 표현한다.
  2. 쇠막대기의 왼쪽 끝은 여는 괄호 ‘ ( ’ 로, 오른쪽 끝은 닫힌 괄호 ‘) ’ 로 표현된다.

위 예의 괄호 표현은 그림 위에 주어져 있다.

쇠막대기는 레이저에 의해 몇 개의 조각으로 잘려지는데, 위 예에서 가장 위에 있는 두 개의 쇠막대기는 각각 3개와 2개의 조각으로 잘려지고, 이와 같은 방식으로 주어진 쇠막대기들은 총 17개의 조각으로 잘려진다.

쇠막대기와 레이저의 배치를 나타내는 괄호 표현이 주어졌을 때, 잘려진 쇠막대기 조각의 총 개수를 구하는 프로그램을 작성하시오.

입력

한 줄에 쇠막대기와 레이저의 배치를 나타내는 괄호 표현이 공백없이 주어진다. 괄호 문자의 개수는 최대 100,000이다.

출력

 

잘려진 조각의 총 개수를 나타내는 정수를 한 줄에 출력한다.

 

 

------

 

레이저, 시작, 끝만 나눠주고 스택을 활용해 계산했다.

 

스틱이 시작할 때, 즉 (면,

카운트 셀 준비를 해야 하니까 스택에 하나씩 넣어준다.

 

스틱이 끝나면

카운트 +1 해주고 스택에서 뺀다

 

if(i<stickLength-1 && stick[i]=== '(' && stick[i+1]===')' )

()는 레이저인데, 문제는 쇠막대기 시작과 끝도 괄호로 표시하기 때문에 제일 먼저 검사한다. continue로 끊어주지 않으면레이저가 시작이나 끝으로 판별될 수도 있기 때문에 continue 를 썼다.

레이저일 경우 -> 지금 내가 ( 이고, 한칸 앞 인덱스는 ) 인경우이다.

다만 이렇게 인덱스+1 연산을 하면 index넘어갈 수 있으니까  i의 범위를 한칸 앞까지로 조정해줘야 한다.

앞서 말한듯이 continue로 밑에 안걸리게 한다.

 

const filePath = process.platform === 'linux' ? 
'/dev/stdin' : './input.txt';

let stick = require('fs').readFileSync(filePath).toString().trim();

// ()는 레이저
// (는 막대기 시작 )는 끝

//(가 나오면 배열에 넣었다가 (다음에 바로 )가 나오면 배열 개수를 셈(빼지 말고)

//) 만 단독으로 있으면-> 바로 pop하면서 개수 추가 +1

let stickLength = stick.length;
let stack = []
let cnt = 0

let i = 0
while(i<stickLength){
    // 레이저 확인
    if(i<stickLength-1 && stick[i]==='(' && stick[i+1]===')'){
        cnt += stack.length
        i += 2
        continue
    }
    if(stick[i]==='('){
        stack.push('(')
        i += 1
    }else{
        stack.pop()
        cnt += 1
        i += 1
    }
}

console.log(cnt)

 

 

---

사담

이걸 포스팅하는 이유는 내가 그냥 뿌듯해서 이다.

이거랑 똑같은 유형의 문제를 싸피에서 처음 풀었을 때가 기억난다. 스택 처음 배우고 애들이랑 머리 맞대면서 이게 뭐꼬????? 했던 기억이 있다.

일단 저 수많은 (()()))들과 그림을 보면 겁부터 난다. 나는 아예 이 문제를 어캐 품 ㅋ 이게 무슨 소리냐 하면서 이미 문제를 해결한 친구들과, 교수님의 설명을 들었던 기억이 난다. 나는 이런거 잘 못풀어~ 하면서 셀프 가스라이팅을 했었던 시절이 있었다.

 

스트릭 남기려고 급하게 풀다가 이문제를 마주쳤는데, 순간 고민했다. 실버라도 쉽게 못 풀거 같았기 때문이다. (이 문제를 처음 봤을 때의 무서운 트라우마가 남아있었는지) 그냥 아 30분 고민하고 안되면 풀이보자~ 하는 마음으로 풀었는데

 

생각보다 너무 단순해서 원트에 쉽게 풀었다. 최근에 브론즈도 가끔 못알아 먹어서 자괴감 느꼈었는데...

이걸 보고 사람은 강해지는 구나... 쫄지말자... 라는 걸 느꼈다. 만약 이 문제가 어려웠던 사람들은 나중에는 더 강해질 수 있을 것이다.