Algorithm/Programmers

Programmers) Lv2 [2020카카오공채] 괄호 변환

삼쓰 웅쓰 2020. 3. 25. 15:04
728x90

출처: https://programmers.co.kr/learn/courses/30/lessons/60058

분류: Lv2


접근방식

문제에서 알고리즘 방법을 단계별로 잘 나눠서 알려주고 있습니다.

잘 읽고 "그대로" 구현만 잘 하면 되는 문제 입니다. 

(그치만 그게 어렵네요 😭)

포인트라면 반복적인 재귀형태가 들어가기 때문에 기능별로 함수를 쪼개서 구현하는 능력이 필요할 것 같네요.

 

출제의도 역시 다음과 같습니다.

주어진 로직을 그대로 구현할 수 있는지 파악

재귀함수를 이해하고 작성할 수 있는지 파악

 

해결방법

저는 주요 기능 (함수)을 크게 4가지로 나눠봤습니다.

1. 문자열을 쪼개는 1 ~ 4 번을 수행하는 함수 (trimming)

func trimming(_ p: String) -> String {
    
    guard !isRight(p) else { return p }
    
    var v = p
    var u: String = String(v.removeFirst())
    var flagCount = 1
    
    while flagCount != 0 {
        let target = v.removeFirst()
        u += String(target)
        flagCount += target == p.first! ? 1 : -1
    }
    
    if isRight(u) {
        return u + trimming(v)
    } else {
        return "(\(trimming(v)))" + transformWrong(u)
    }
    
}

2. 올바른 문자열인지 확인하기 (isRight) 

func isRight(_ str: String) -> Bool {
    var openCount = 0
    
    for c in str {
        if openCount < 0 { return false }
        openCount += c == "(" ? 1 : -1
    }
    
    return openCount == 0
}

3. u가 올바른 문자열이 아닐 때 변환하는 함수 (transformWrong)

func transformWrong(_ str: String) -> String {
    var targetStr = str
    targetStr.removeFirst()
    targetStr.removeLast()
    
    return targetStr.reversedParenthesis
}

4. 괄호 뒤집기 (reversedParenthesis)

extension String {
    var reversedParenthesis: String {
        var result = ""
        for c in self {
            result += (c == "(") ? ")" : "("
        }
        return result
    }
}

다음과 같이 개별적인 기능을 나눠서 함수를 구현했다면 나머지는 정말 문제의 설명을 잘 따라서 수행해주면 됩니다.

단, 예제만 보고 "유추" 해서 푸는 것이 아니라 문제의 알고리즘을 읽고 그대로 구현해주셔야 실수를 방지할 수 있습니다.
(네 저처럼 실수 하지 않으시려면요...)

 

요약해서 대강 설명드리면...

 

u가 올바른 문자열이라면 u + trmming(v)

v를 조작해서 u 뒤에 v를 붙입니다.

 

u가 올바른 문자열이라면 ( trimming(v) ) + tramsformWrong(u)

v를 조작한 다음 뒤에 u를 붙입니다.

 

총 풀이 입니다.

import Foundation

extension String {
    var reversedParenthesis: String {
        var result = ""
        for c in self {
            result += (c == "(") ? ")" : "("
        }
        return result
    }
}

func isRight(_ str: String) -> Bool {
    var openCount = 0
    
    for c in str {
        if openCount < 0 { return false }
        openCount += c == "(" ? 1 : -1
    }
    
    return openCount == 0
}

func trimming(_ p: String) -> String {
    
    guard !isRight(p) else { return p }
    
    var v = p
    var u: String = String(v.removeFirst())
    var flagCount = 1
    
    while flagCount != 0 {
        let target = v.removeFirst()
        u += String(target)
        flagCount += target == p.first! ? 1 : -1
    }
    
    if isRight(u) {
        return u + trimming(v)
    } else {
        return "(\(trimming(v)))" + transformWrong(u)
    }
    
}

func transformWrong(_ str: String) -> String {
    var targetStr = str
    targetStr.removeFirst()
    targetStr.removeLast()
    
    return targetStr.reversedParenthesis
}

func solution(_ p:String) -> String {
    
    guard !p.isEmpty else { return "" }
    
    return trimming(p)
}

 

배운점

구현력은 기본 중의 기본.. 하라는 대로 하는 것도 못하면 안되겠죠?

 

회고

너무 느리다.

빠르게 빠르게 

연습 또 연습 😫😫😫