안녕하세요. 회사와 함께 성장하고 싶은 KOSE입니다.

이번 포스팅은 백준 Java vs C++ 자바 풀이를 진행하도록 하겠습니다.

문제출처:https://www.acmicpc.net/problem/3613

 

3613번: Java vs C++

Java 예찬론자 김동규와 C++ 옹호가 김동혁은 서로 어떤 프로그래밍 언어가 최고인지 몇 시간동안 토론을 하곤 했다. 동규는 Java가 명확하고 에러가 적은 프로그램을 만든다고 주장했고, 동혁이는

www.acmicpc.net

 

1. 풀이 소스

 

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        String str = br.readLine();
        
        // 시작이 대문자이거나 _, 마지막이 _ 불가
        if (str.charAt(0) <= '_' || str.charAt(str.length() - 1) == '_') {
            System.out.println("Error!");
            return;
        }
        
        // __ 불가 _A 불가 A_불가
        boolean upperCase = false; // 만약 대문자가 있다면 c++로만 바꿀 수 있음
        boolean toJava = false; // false라면 c++, true라면 자바로 바꾸기
        char pre = str.charAt(0); // 이전 문자 파악
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            
            if (ch <= 'Z') {
                if (toJava) { // _A로 끝나면 안되므로 _ 나왔는지 판단 (toJava라면 _이 나옴)
                    System.out.println("Error!");
                    return;
                } 
                upperCase = true; // 대문자 true 설정
            }
            
            if (ch == '_') { // 만약 _가 있는데 대문자가 섞여 있다면 불가
                if (upperCase || pre == '_') {
                    System.out.println("Error!");
                    return;
                }
                toJava = true;
            }
            pre = ch;
        }
        
        
        if (toJava) { // 자바로 바꿔야 함
            boolean nextUpper = false; // 다음이 대문자가 나와야함
            for (int i = 0; i < str.length(); i++) {
                char ch = str.charAt(i);
                if (nextUpper) {
                    sb.append(String.valueOf(ch).toUpperCase()); // 문자열 대문자로 변경
                    nextUpper = false; // 초기화
                } else {
                    if (str.charAt(i) == '_') nextUpper = true; // 다음 문자열 대문자로 설정
                    else sb.append(ch);
                }
            }
        }
        else { // c++로 바꿔야 함
            for (int i = 0; i < str.length(); i++) {
                char ch = str.charAt(i);
                if (ch <= 'Z') { // 만약 대문자라면
                    sb.append("_"); // "_소문자"로 바꾸기
                    sb.append(String.valueOf(ch).toLowerCase());
                } else sb.append(ch);
            }            
        }
        
        System.out.println(sb);
    }
}

 

2. 풀이 중점 사항

 

해당 문제는 반례를 생각해 내는 것이 중요한 문제였습니다.

안 되는 경우

  • _ 로 시작   ex)  "_a"
  • 대문자로 시작 ex) "Ab"
  • _로 끝남 ex) "ab_"
  • 대문자와 _이 같이 쓰임 ex) "aB_b"
  • __이 두 개 이상이 연속으로 쓰임 ex) "a__b"

 

// 시작이 대문자이거나 _, 마지막이 _ 불가
if (str.charAt(0) <= '_' || str.charAt(str.length() - 1) == '_') {
    System.out.println("Error!");
    return;
}

시작이 대문자이거나 "_"인 경우, 마지막 문자열이 "_"로 끝나는 경우는 처음에 확인이 가능합니다.

 

// __ 불가 _A 불가 A_불가
boolean upperCase = false; // 만약 대문자가 있다면 c++로만 바꿀 수 있음
boolean toJava = false; // false라면 c++, true라면 자바로 바꾸기
char pre = str.charAt(0); // 이전 문자 파악
for (int i = 0; i < str.length(); i++) {
    char ch = str.charAt(i);
    
    if (ch <= 'Z') {
        if (toJava) { // _A로 끝나면 안되므로 _ 나왔는지 판단 (toJava라면 _이 나옴)
            System.out.println("Error!");
            return;
        } 
        upperCase = true; // 대문자 true 설정
    }
    
    if (ch == '_') { // 만약 _가 있는데 대문자가 섞여 있다면 불가
        if (upperCase || pre == '_') {
            System.out.println("Error!");
            return;
        }
        toJava = true;
    }
    pre = ch;
}

 

모든 문자가 전부 소문자와 대문자로만 이루어져 있다면, 이는 Java의 변수명 형태로 작성된 것입니다.

따라서, c++로 변경 가능합니다.

반면, 모든 문자가 소문자와 "_"로만 쓰인 경우는 Java로 변경이 가능합니다.

이와 같이 O(n)으로 탐색하며 어떠한 문자로 변경 가능한지 판단합니다.

 

if (toJava) { // 자바로 바꿔야 함
    boolean nextUpper = false; // 다음이 대문자가 나와야함
    for (int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);
        if (nextUpper) {
            sb.append(String.valueOf(ch).toUpperCase()); // 문자열 대문자로 변경
            nextUpper = false; // 초기화
        } else {
            if (str.charAt(i) == '_') nextUpper = true; // 다음 문자열 대문자로 설정
            else sb.append(ch);
        }
    }
}
else { // c++로 바꿔야 함
    for (int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);
        if (ch <= 'Z') { // 만약 대문자라면
            sb.append("_"); // "_소문자"로 바꾸기
            sb.append(String.valueOf(ch).toLowerCase());
        } else sb.append(ch);
    }            
}

 

이후 다시 O(n)으로 바꿔야 하는 방향으로 문자를 바꿀 수 있습니다.

자세한 풀이는 주석으로 작성하였습니다.

이상으로 Java vs C++ 자바 풀이를 마치도록 하겠습니다.

감사합니다.!

+ Recent posts