[알고리즘] 괄호 변환

백상휘·2020년 9월 7일
0

알고리즘

목록 보기
4/4

해당 문제는 프로그래머스(https://programmers.co.kr/learn/courses/30/lessons/60058)에 출제된 문제를 채점한 결과를 토대로 작성하였습니다.


특별히 해당 문제는 입출력 예 화면을 올렸습니다. 카카오는 역시 카카오라는 생각이 든 것은 풀이방법을 제시해 줌에도 불구하고 어려운 문제를 만들어냈다는 것에 다시 한번 감탄한 문제입니다.

이 문제는 개인적으로 생각해보았을 때 '재귀함수를 응용할 수 있는가' 라는 질문에 대한 대답인 것 같습니다. 실제 웹 프로그래밍이나 앱 프로그래밍에서는 많이 써보지 않아서 이해하는 것이 힘들었지만 이번 기회에 한번 써볼 수 있어서 좋았습니다.

이 문제에는 두 개의 키워드가 있습니다.
균형잡힌 괄호 문자열 => "(", ")" 의 갯수가 같은 문자열.
(예. "(())", "))((", ")((())", "()")
올바른 괄호 문자열 => "(", ")" 의 갯수와 짝이 맞는 문자열.
(예. "()", "(())", "()(())", "(()())")

'매개변수 설명' 에 보면 유추해 볼 수 있는 정보는 p 파라미터는 균형잡힌 괄호 문자열이며, 짝수(2이상)입니다. 이를 통해 구현해야 할 guard문을 구현할 필요는 없었습니다.

import Foundation

func solution(_ p:String) -> String {
    var p = p
    return splitRepeatedly(vValue: &p)
}

//균형잡힌 괄호 문자열 반환
func splitBracket(_ str: String) -> [String: String] {
    var str = str
    var uTemp = String(str.removeFirst())
    
    while uTemp.filter({$0=="("}).count != uTemp.filter({$0==")"}).count {
        uTemp += String(str.removeFirst())
    }
    
    return ["u":uTemp,"v":str]
}

//올바른 괄호 문자열인지
func isRightBracket(_ str: String) -> Bool {
    guard str.first == "(" && str.count != 0 && str.count.isMultiple(of: 2) else {
        return false
    }
    var str = str
    
    while !str.isEmpty {
        let middlePoint = str.firstIndex(of: str.first! == ")" ? "(" : ")")!
        let lhs = String(str[str.index(before: middlePoint)])
        let rhs = String(str[middlePoint])
        
        if lhs != rhs {
            str = String(str[..<str.index(before: middlePoint)]+str[str.index(after: middlePoint)...])
        } else {
            break
        }
    }
    
    return str.isEmpty
}

func splitRepeatedly(vValue: inout String) -> String {
    let splited = splitBracket(vValue)
    
    if var uValue = splited["u"], var vValue = splited["v"] {
        let temp = vValue == "" ? vValue : splitRepeatedly(vValue: &vValue) //재귀함수를 호출하는 부분. v로 호출할 수 없을 때까지 수행.
        if isRightBracket(uValue) { //올바른 괄호 문자열이라면
            return uValue + temp
        } else { //올바른 괄호 문자열이 아니라면
            uValue.removeFirst()
            uValue.removeLast()
            return "("+temp+")"+uValue.map{$0 == "(" ? ")" : "("}.reduce(""){$0+$1}
        }
    }
    return vValue
}

제가 풀때는 10시쯤 시작하여 새벽1시까지 못풀었는데, 4-2 의 설명을 잘 읽지 않아서 재귀함수를 호출하는 조건을 제대로 파악하지 못했습니다.

한번 풀어보시길 바랍니다.

profile
plug-compatible programming unit

0개의 댓글