Problem:
Problem P04: CamelCase

プログラミングにおける識別子（変数や関数）の命名では、
単語を連結した複合語が使われる。
しかし、そのまま連結すると単語の区切りがわからなくなるため、
一般的に以下の命名規則の中から統一するものを選び適用する：

Upper CamelCase　にする

単語を直接連結し複合語とし、各単語の先頭文字のみを大文字にする。

例： GetUserName

Lower CamelCase　にする

単語を直接連結し複合語とし、各単語の先頭文字のみを大文字にする。ただし、複合語の先頭文字は小文字にする。

例： getUserName

アンダースコアで繋ぐ

単語をアンダースコアで連結し複合語とする。単語の文字はすべて小文字にする。

例： get_user_name

与えられた識別子を、指定された命名規則を適用して出力するプログラムを作成せよ。
与えられる識別子は、上記の命名規則のいづれかが既に適用されているものとする。

Input

入力として複数のデータセットが与えられる。各データセットは以下の形式で与えられる：

name type （識別子、命名規則：　空白区切りの文字列と文字）

typeは命名規則を示す文字であり、以下の表の通りとする：

type

命名規則

U

Upper CamelCase にする

L

Lower CamelCase にする

D

アンダースコアで繋ぐ

与えられる識別子の文字数は 1 以上 100 以下である。

type が 'X' のとき入力の終わりとする。この入力に対する出力を行ってはならない。

Output

各データセットについて、命名規則を適用した識別子を1行に出力せよ。

Sample Input

get_user_name L
getUserName U
GetUserName D
EndOfInput X

Output for the Sample Input

getUserName
GetUserName
get_user_name

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.*;

public class Main {
    private static final String EOF = "X";

    public static void main(String[] args) {
        try(Scanner scn = new Scanner(System.in)) {
            String[] line = null;
            while((line = scn.nextLine().split(" ")) != null && !line[1].equals(EOF)) {
                System.out.println(encode(decode(line[0]), line[1]));
            }
        }
    }

    private static String[] decode(String str) {
        String[] rslt = null;
        if(str.indexOf("_") >= 0) {
            rslt = decodeSnake(str);
        } else {
            if(Character.isUpperCase(str.charAt(0))) {
                rslt = decodePascal(str);
            } else {
                rslt = decodeCamel(str);
            }
        }
        return rslt;
    }

    private static String[] decodePascal(String str) {
        return decodeCamel(str);
    }

    private static String[] decodeCamel(String str) {
        ArrayList<String> list = new ArrayList<>();
        for(int i = 1; i < str.length(); i++) {
            if(Character.isUpperCase(str.charAt(i))) {
                list.add(str.substring(0, i).toLowerCase());
                str = str.substring(i);
                i = 1;
            }
        }
        list.add(str.toLowerCase());
        return list.toArray(new String[0]);
    }

    private static String[] decodeSnake(String str) {
        return str.split("_");
    }

    private static String encode(String[] words, String op) {
        String rslt = null;
        switch(op) {
          case "U":
            rslt = encodePascal(words);
            break;
          case "L":
            rslt = encodeCamel(words);
            break;
          case "D":
            rslt = encodeSnake(words);
            break;
          default:
            assert false;
        }
        return rslt;
    }

    private static String encodePascal(String[] words) {
        StringBuilder sb = new StringBuilder();
        for(String word : words) {
            sb.append(Character.toUpperCase(word.charAt(0)) + word.substring(1));
        }
        return sb.toString();
    }

    private static String encodeCamel(String[] words) {
        StringBuilder sb = new StringBuilder(words[0]);
        for(int i = 1; i < words.length; i++) {
            sb.append(Character.toUpperCase(words[i].charAt(0)) + words[i].substring(1));
        }
        return sb.toString();
    }

    private static String encodeSnake(String[] words) {
        StringBuilder sb = new StringBuilder(words[0]);
        for(int i = 1; i < words.length; i++) {
            sb.append("_" + words[i]);
        }
        return sb.toString();
    }
}