본문 바로가기
Coding Test

2. 괄호 문법 검사기 (pop()을 조건문 안에 쓰는 경우 발생하는 오류)

by Daen12 2022. 11. 12.

[문제 & 입출력 예]

 

요구 사항은 아래와 같다.

 

1. 요구사항 : 객체 분석 정보를 출력

배열의 중첩된 깊이를 분석하고, 원소의 갯수를 출력한다.

const data = "[1,2,[3,4,[5,[6]]]]"
run(data)
> "배열의 중첩된 깊이 수준은 4이며, 총 6개의 원소가 포함되어 있습니다"

 

2. 요구사항 : 괄호가 매칭에 문제가 있는 경우 오류내용을 출력한다.

괄호의 갯수가 제대로 인지 파악한다.

const data = "[1,2,[3,4,[5,[6]]"  
run(data);
> '닫는 괄호가 일치하지 않습니다'

 

[풀이 및 시행착오]

 

Version 1 |  먼저 변수만을 활용하여 코드를 짰다.

const test = "[1,2,[3,4,[5,[6]]]]"

function arrayChecker(data){
    let bracketMatch = 0;
    let bracketCount = 0;
    let itemCount = 0;
    stack = [];

    for (let i=0; i<data.length; i++){
        if (data[i] === '['){
            bracketMatch++;
            bracketCount++;
        } else if (data[i] === ']'){
            bracketMatch--;
        } else if(data[i] !== ','){
            itemCount++;
        };
    }

    if(bracketMatch === 0){
        return `배열의 중첩된 깊이 수준은 ${bracketCount}이며, 총 ${itemCount}개의 원소가 포함되어 있습니다.`;
    } else{
        return "닫는 괄호가 일치하지 않습니다.";
    }
}

console.log(arrayChecker(test));

- 괄호를 카운트할 변수, 괄호가 매칭되었는지 확인할 변수, 원소 개수를 확인할 변수를 세 개 만들어 주었다.

- '['나 ']', 그리고 ','가 아니면 숫자이므로 마지막 조건에서 itemCount변수에 1을 더해주도록 했다.

- 변수를 줄이고 더 간단하게 짤 방법은 없을까?

 

 

Version 2 |  Push()와 pop()을 활용한 두번째 버전을 만들었다.

function arrayChecker(data){
    let bracketCount = 0;
    let itemCount = 0;
    const stack = [];
    const error = "닫는 괄호가 일치하지 않습니다."
    
    for (let i=0; i<data.length; i++){
        if (data[i] === '['){
            stack.push(data[i]);
            bracketCount++;

        } else if (data[i] === ']'){
            if(stack.pop()===undefined){ //pop()이 두번 시행되는 상황 발생
                return error;
            } else {
            stack.pop();      
        }
        } else if(data[i] !== ','){
            itemCount++;
        };
    }

    if(stack.length === 0){
        return `배열의 중첩된 깊이 수준은 ${bracketCount}이며, 총 ${itemCount}개의 원소가 포함되어 있습니다.`;
    } else{
        return error;
    }
}

console.log(arrayChecker(test));

첫번째 else문의 안에 if 조건을 넣어주었는데, 이때 스택의 길이가 0이면 괄호가 비대칭인 것이므로 if문이 동작하도록 하였다.

 

그런데 여기서, if(stack.pop() === undefined) 정확한 답을 리턴하지 않는다.

여기서 원래 조건문 안의 pop()은 stack 변수로 할당된 배열에 pop을 시행할 수 있는 원소가 들어있는지 확인하는 용으로 썼는데,

디버깅을 시도한 결과 이 구간을 지나면 stack에 있는 멀쩡한 숫자들이 pop 된다는걸 알게됐다. (따라서 아래에 있는 pop을 포함하면 pop()이 두번 동작한다)

 

이 현상에 대해서 멘토님께 여쭤봤는데, 아래와 같이 설명을 해 주셨다.

if (집에 있는 젓가락 갯수 세오기() === 20) { ... } 이런 조건문이 있다고 하면
젓가락 갯수를 세지 않고는 저게 20개랑 같은지 아닌지를 계산할 수 없겠죠?

따라서 위의 코드는 if문 안에 있더라도 이미 stack 배열에 대해서 pop()을 시행하는 것이다!

 

코드가 잘 동작하도록 이를 아래와 같이 수정해주었다.

function arrayChecker(data){
    let bracketCount = 0;
    let itemCount = 0;
    const stack = [];
    const error = "닫는 괄호가 일치하지 않습니다."
    
    for (let i=0; i<data.length; i++){
        if (data[i] === '['){
            stack.push(data[i]);
            bracketCount++;

        } else if (data[i] === ']'){
            if(!stack.length){ //스택의 길이가 0이라면,
                return error;
            } else {
            stack.pop();      
        }
        } else if(data[i] !== ','){
            itemCount++;
        };
    }

    if(stack.length === 0){
        return `배열의 중첩된 깊이 수준은 ${bracketCount}이며, 총 ${itemCount}개의 원소가 포함되어 있습니다.`;
    } else{
        return error;
    }
}

console.log(arrayChecker(test));

위 코드는 잘 동작함이 확인된다.

댓글