1️⃣ 문제

문제 - 괄호 변환

2️⃣ 풀이 방법 및 코드

사실 문제에서 시키는대로, 아래와 같이 재귀 코드를 작성하면 되는 구현 문제였다.

1. 입력이 빈 문자열인 경우, 빈 문자열을 반환합니다. 
2. 문자열 w를 두 "균형잡힌 괄호 문자열" u, v로 분리합니다. 단, u는 "균형잡힌 괄호 문자열"로 더 이상 분리할 수 없어야 하며, v는 빈 문자열이 될 수 있습니다. 
3. 문자열 u가 "올바른 괄호 문자열" 이라면 문자열 v에 대해 1단계부터 다시 수행합니다. 
  3-1. 수행한 결과 문자열을 u에 이어 붙인 후 반환합니다. 
4. 문자열 u가 "올바른 괄호 문자열"이 아니라면 아래 과정을 수행합니다. 
  4-1. 빈 문자열에 첫 번째 문자로 '('를 붙입니다. 
  4-2. 문자열 v에 대해 1단계부터 재귀적으로 수행한 결과 문자열을 이어 붙입니다. 
  4-3. ')'를 다시 붙입니다. 
  4-4. u의 첫 번째와 마지막 문자를 제거하고, 나머지 문자열의 괄호 방향을 뒤집어서 뒤에 붙입니다. 
  4-5. 생성된 문자열을 반환합니다.

다만 풀면서 고민했던 점으로 올바른 괄호 문자열을 확인하는 방법이었다.

처음에는 스택으로 문자열을 다 검사했었는데,

균형잡힌 문자열이 들어온다는 조건 때문에 u의 첫번째 원소가 “(“ 이기만 하면 무조건 u가 올바른 문자열임을 알 수 있다는 점을 깨달았다.

String을 extension 하여 확인할 수 있는 Bool 프로퍼티를 이용하였다.(isRigthP)

소스 코드

extension String {
    // 올바른 괄호 문자열인지 확인하는 Bool
    var isRightP: Bool {
        return self.first! == "(" ? true: false
    }
}

// 올바른 괄호 문자열로 수정
func edit(_ u: String, _ v: String) -> String {
    var w = "(\(v))"
    
    u.enumerated().forEach {
        if $0.0 != 0 && $0.0 != u.count - 1 {
            w += $0.1 == ")" ? "(": ")"
        }
    }
    return w
}

func implement(_ p: String) -> String {
    // 입력이 빈 문자열인 경우, 빈 문자열을 반환
    guard !p.isEmpty else { return "" }
    
    // 문자열 w를 두 "균형잡힌 괄호 문자열" u, v로 분리
    var pCopy = p
    var left = 0, right = 0
    var u = "", v = ""
    repeat {
        switch pCopy.first! {
            case "(":
            left += 1
            default:
            right += 1
        }
        u.append(pCopy.removeFirst())
    } while !pCopy.isEmpty && left != right
    v = pCopy
    
    // 문자열 u가 "올바른 괄호 문자열" 이라면 문자열 v에 대해 1단계부터 다시 수행
    // 수행한 결과 문자열을 u에 이어 붙인 후 반환
    return u.isRightP ? u + (v): edit(u, implement(v))
}

func solution(_ p:String) -> String {
    return implement(p)
}

3️⃣ 이 문제를 풀면서 되새긴 점

repeat-while 구문

늘 while문만 써오다보니, repeat-while 구문 존재를 까먹고 있었다. 이번 문제처럼 처음에는 조건 검사없이 구문을 반복해야 할 때 유용하게 사용하도록 하자!

repeat {
  /*실행 구문*/
} while 조건