본문 바로가기
코딩 테스트/백준

[백준] (Swift) 3613번: Java vs C++

by Dev.Andy 2023. 3. 21.

📌 문제

3613번: Java vs C++

 

📌 풀이 개요

이 문제의 핵심은 Java 형식(Camel case)과 Cpp 형식(Snake case)의 특징을 확인하여 이를 서로 변환하는 것이다.

 

  • 각 형식의 예외 조건을 찾아 해당 형식에 부합한지를 판별해야 한다.
  • 변수명의 이름이 바뀔 때마다 Java 형식은 대문자가 되고, Cpp 형식은 밑줄('_')이 따라 붙는다.
  • 여기에 맞지 않는 것은 예외 처리로 판별한다.

 

📌 풀이

1. Java 형식이 아닐 때

  • 첫글자가 대문자일 경우
  • 밑줄이 하나라도 있을 경우

2. Cpp 형식이 아닐 때

  • 양끝에 밑줄이 있을 경우
  • 밑줄이 2개 이상 붙어 있을 경우
  • 대문자가 하나라도 있을 경우

이제 위의 형식을 판별했다면 서로 다른 형식으로 변환하면 된다.

3. Cpp에서 Java로 변환할 때: 밑줄 다음의 단어를 대문자로 바꾸고 밑줄 지우기

  • '다음 인덱스'를 고려하면 인덱스 범위를 초과하는 에러가 날 수 있다.
  • 이를 방지하기 위하여 대문자를 알려주는 변수 flag를 이용했다. 

 

4. Java에서 Cpp로 변환할 때: 대문자 앞에 밑줄을 넣고 대문자를 소문자로 바꾸기

  • 인덱스 중간에 밑줄을 삽입해야 하기에 추가할 때마다 인덱스가 하나씩 추가된다.
  • 새 인덱스를 매번 고려하기에 더해야 할 인덱스 변수 j를 이용했다.

 

📌 코드

import Foundation

// 대문자 소문자를 각각 문자열로 상수에 할당
let upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
let lowerCase = "abcdefghijklmnopqrstuvwxyz"

// 대문자가 맞는지 검사하는 함수 정의
func isUpperCase(_ letter: Character) -> Bool {
    for capital in upperCase {
        if (letter == capital) {
            return true
        }
    }
    
    return false
}

// 대문자가 맞는지 검사하는 함수 정의
func isLowerCase(_ letter: Character) -> Bool {
    for small in lowerCase {
        if (letter == small) {
            return true
        }
    }
    
    return false
}

// Java 형식인지 검사하는 함수 정의
func isJavaFormat(_ str: String) -> Bool {
    // Java 형식에서 첫글자가 대문자일 경우 거짓
    if (isUpperCase(str[str.startIndex])) {
        return false
    }
    
    // 하이픈이 하나라도 있을 경우 거짓
    for char in str {
        if (char == "_") {
            return false
        }
    }
    
    // 나머지 경우 참
    return true
}

// Cpp 형식인지 검사하는 함수 정의
func isCppFormat(_ str: String) -> Bool {
    // 첫 인덱스나 마지막 인덱스에 하이픈이 있는 경우 거짓
    if (str[str.startIndex] == "_" || str[str.index(before: str.endIndex)] == "_") {
        return false
    }
    
    // 연속된 하이픈이 있는 경우 거짓
    if (str.contains("__")) {
        return false
    }
    
    // Cpp 형식은 대문자가 하나라도 있으면 거짓
    for char in str {
        if (isUpperCase(char)) {
            return false
        }
    }
    
    // 나머지 경우 참
    return true
}

// Cpp 형식을 Java 형식으로 바꾸는 함수 정의
func convertCppToJava(_ str: String) -> String {
    var arr: [Character] = Array(str)
    let range = arr.count
    var flag = 0
    var result = String()
    
    for i in 0..<range {
        if (arr[i] == "_" && flag == 0) {
            flag += 1
            continue
        }
            
        else if (flag == 1) {
            arr[i] = Character(arr[i].uppercased())
            flag = 0
        }
    }
    result = String(arr).components(separatedBy: ["_"]).joined()
    
    return result
}

// Java 형식을 Cpp 형식으로 바꾸는 함수 정의
func convertJavaToCpp(_ str: String) -> String {
    var arr: [Character] = Array(str)
    let range = arr.count
    var result = String()
    var j = 0
    
    for i in 0..<range {
        // insert 때문에 이후에 'i'가 아닌 'i + j' 인덱스에 접근
        if (isUpperCase(arr[i + j])) {
            arr[i + j] = Character(arr[i + j].lowercased())
            arr.insert("_", at: i + j)
            j += 1  // 요소 삽입 후 j 증가
        }
    }
    result = String(arr)
    
    return result
}

// 주어진 입력을 input에 문자열로 할당
var input = readLine()!

// 결괏값을 빈 문자열로 할당
var result = String()

// Cpp 형식일 경우 Java 형식으로 변형하여 결괏값에 할당
if (isCppFormat(input)) {
    result = convertCppToJava(input)
}

// Java 형식일 경우 Cpp 형식으로 변형하여 결괏값에 할당
else if (isJavaFormat(input)) {
    result = convertJavaToCpp(input)
}

// 둘 다 아니면 "Error!"를 결괏값에 할당
else {
    result = "Error!"
}

// 결괏값 출력
print(result)

 

📌 풀이

isUppercase/isLowercase 프로퍼티를 활용할 줄 몰라서 함수를 직접 만들었다.... 아이러니하게도 함수나 자료형을 제대로 써 보게 되는 기회가 되었다. Swift를 통해 문자열을 자유자재로 다뤄볼 수 있는 좋은 문제였다.

 

거의 다 풀어서 입력한 문자가 모두 잘 출력되었는데, 에러의 경우에 "Error!"를 "Error"로 잘못 출력하여 이를 찾기까지 3~4시간을 헤맸다. 문제 좀 잘 읽자 하...

 

댓글