(Swift) 백준 2504 괄호의 값

SteadySlower·2022년 8월 23일
0

Coding Test

목록 보기
130/305

2504번: 괄호의 값

문제 풀이 아이디어

괄호의 짝을 맞추는 문제로 전형적인 stack을 활용해서 풀어야 하는 문제입니다. 하지만 이 문제의 복잡한 점은 stack에 괄호만 들어가는 것이 아니라 괄호의 값을 넣어서 계산해주어야 한다는 것인데요. 여는 괄호를 push하고 닫는 괄호일 때 pop해서 짝을 맞추어보는 것은 동일하지만 중간에 짝을 이룰 때마다 계산해서 stack에 푸시합니다.

말로면 설명하니 쉽지 않네요. (()[[]]) 의 괄호의 값을 계산해보면서 설명을 해보겠습니다.

예시

예외 처리 points

  1. 닫는 괄호가 나와서 pop을 할 때 여는 괄호의 유형 (소괄호 or 대괄호)가 맞지 않으면 예외 처리합니다.
  2. 닫는 괄호가 나왔을때 stack이 비어있으면 예외 처리합니다. (짝을 맞출 수 없음)
  3. 마지막에 괄호 연산이 끝나고 stack에 남은 값을 모두 더할 때 stack 안에 괄호가 남아있다면 예외 처리합니다.

코드

import Foundation

// 입력 받기
let string = readLine()!.map { String($0) }
var stack = [String]()

// 올바르지 않은 문자열인 경우 0 출력하고 프로그램 종료
func exitWithPrintingZero() {
    print(0)
    exit(0)
}

// 괄호들을 순회하면서
for s in string {
    //1. 여는 괄호의 경우 stack에 push
    if s == "(" || s == "[" {
        stack.append(s)
    //2. 닫는 소괄호의 경우
    } else if s == ")" {
        var temp = 0 // 계산 결과를 담아놓는 임시 변수
        guard !stack.isEmpty else { exitWithPrintingZero(); break }
            //👉 만약에 stack이 비었다면 여는 괄호와 짝을 이룰 수 없으므로 종료
        while !stack.isEmpty {
            let popped = stack.popLast()!
            //2-1. 여는 괄호를 만나면 지금까지의 계산 결과에 2를 곱해서 (단 0인 경우 2) push하고 break (짝을 찾음)
            if popped == "(" {
                stack.append(temp == 0 ? "2" : "\(2 * temp)")
                break
            //2-2. 짝이 맞지 않는 여는 괄호를 만나면 잘못된 짝이므로 종료
            } else if popped == "[" {
                exitWithPrintingZero()
            //2-3. 숫자를 만나면 덧셈 계산
            } else {
                temp += Int(popped)!
            }
        }
    //3. 닫는 대괄호의 경우
    } else if s == "]" {
        var temp = 0
        guard !stack.isEmpty else { exitWithPrintingZero(); break }
        while !stack.isEmpty {
            //3-1. 여는 괄호를 만나면 지금까지의 계산 결과에 3를 곱해서 (단 0인 경우 3) push하고 break (짝을 찾음)
            let popped = stack.popLast()!
            if popped == "[" {
                stack.append(temp == 0 ? "3" : "\(3 * temp)")
                break
            //3-2. 짝이 맞지 않는 여는 괄호를 만나면 잘못된 짝이므로 종료
            } else if popped == "(" {
                exitWithPrintingZero()
            //3-3. 숫자를 만나면 덧셈 계산
            } else {
                temp += Int(popped)!
            }
        }
    }
}

var ans = 0

// stack에 남은 숫자 더해서 답 구하기
for str in stack {
    guard let num = Int(str) else { exitWithPrintingZero(); break }
    ans += num
}

print(ans)
profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글