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 Ruby (judge verdict: Accepted)

def main
  answers = []
  loop do
    str,pattern = gets.chomp.split(' ')
    break if pattern.eql?('X')

    answers << case pattern
    when 'U'
      conversion_to_upper_camel_case(str)
    when 'L'
      conversion_to_lower_camel_case(str)
    when 'D'
      conversion_to_snake_case(str)
    end
  end

  answers.each {|answer|puts answer}
end

def split_word str
  words = []
  word = ''
  str.length.times do |i|
    if str[i].match(/_/)
      words << word
      word = ''
    elsif str[i].match(/[A-Z]/)
      words << word unless i == 0
      word = str[i]
    else
      word << str[i]
    end
  end
  words << word
  words
end

def to_first_char_upcase word
  result_word = ''
  word.length.times do |i|
    if i == 0
      result_word << word[i].upcase
    else
      result_word << word[i].downcase
    end
  end
  result_word
end

def conversion_to_upper_camel_case str
  conversion_word = ''
  words = split_word(str)
  words.each do |word|
    conversion_word << to_first_char_upcase(word)
  end
  conversion_word
end

def conversion_to_lower_camel_case str
  conversion_word = ''
  words = split_word(str)
  words.each_with_index do |word, i|
    if i == 0
      conversion_word << word.downcase
    else
      conversion_word << to_first_char_upcase(word)
    end
  end
  conversion_word
end

def conversion_to_snake_case str
  words = split_word(str)
  words.each.map{|word|word.downcase}.join('_')
end

main