import bisect
from typing import List


def convert_romaji_to_hiragana(romaji: str) -> str:
    if len(romaji) == 0:
        return ''
    for i in range(min(4, len(romaji)), 0, -1):
        key = romaji[0:i]
        pos = bisect.bisect(ROMAJI_KEYS, key)
        if pos != len(ROMAJI_KEYS) and ROMAJI_KEYS[pos - 1] == key:
            return ROMAJI_VALUES[pos - 1] + convert_romaji_to_hiragana(romaji[i:])
    if len(romaji) >= 2 and romaji[0] == romaji[1] and romaji[0] in VOWELS:
        return 'っ' + convert_romaji_to_hiragana(romaji[1:])
    if romaji[0] == 'n':
        return 'ん' + convert_romaji_to_hiragana(romaji[1:])
    return romaji[0] + convert_romaji_to_hiragana(romaji[1:])


def convert_romaji_to_hiragana_predictively(romaji: str) -> List[str]:
    if not romaji:
        return ['']
    for i in range(min(4, len(romaji)), 0, -1):
        key = romaji[0:i]
        pos = bisect.bisect(ROMAJI_KEYS, key)
        if pos != len(ROMAJI_KEYS) and ROMAJI_KEYS[pos - 1] == key:
            return concat(ROMAJI_VALUES[pos - 1], convert_romaji_to_hiragana_predictively(romaji[i:]))
    if len(romaji) >= 2 and romaji[0] == romaji[1] and not (romaji[0] in VOWELS) and romaji[0].islower():
        return concat('っ', convert_romaji_to_hiragana_predictively(romaji[1:]))
    elif romaji[0] == 'n':
        return concat('ん', convert_romaji_to_hiragana_predictively(romaji[1:]))
    elif len(romaji) <= 2:
        results = predictive_search(romaji)
        if len(results) == 0:
            return concat(romaji[0:1], convert_romaji_to_hiragana_predictively(romaji[1:]))
        else:
            if romaji[0].isalpha() and not(romaji[0] in VOWELS):
                a = concat('っ', results)
                b = results
                return a + b
            else:
                return results
    return concat(romaji[0:1], convert_romaji_to_hiragana_predictively(romaji[1]))


def concat(prefix: str, sources: List[str]) -> List[str]:
    result = []
    for source in sources:
        result.append(prefix + source)
    return result


def predictive_search(key: str) -> List[str]:
    stop = key[0:-1] + chr(ord(key[-1]) + 1)
    start_pos = bisect.bisect(ROMAJI_KEYS, key)
    end_pos = bisect.bisect(ROMAJI_KEYS, stop)
    return ROMAJI_VALUES[start_pos:end_pos]


VOWELS = "aiueon"
ROMAJI_KEYS = [
    "-",
    "~",
    "a",
    "ba",
    "be",
    "bi",
    "bo",
    "bu",
    "bya",
    "bye",
    "byi",
    "byo",
    "byu",
    "ca",
    "ce",
    "cha",
    "che",
    "chi",
    "cho",
    "chu",
    "ci",
    "co",
    "cu",
    "da",
    "de",
    "dha",
    "dhe",
    "dhi",
    "dho",
    "dhu",
    "di",
    "do",
    "du",
    "e",
    "fa",
    "fe",
    "fi",
    "fo",
    "fu",
    "fwa",
    "fwe",
    "fwi",
    "fwo",
    "fwu",
    "fya",
    "fye",
    "fyi",
    "fyo",
    "fyu",
    "ga",
    "ge",
    "gi",
    "go",
    "gu",
    "gwa",
    "gwe",
    "gwi",
    "gwo",
    "gwu",
    "gya",
    "gye",
    "gyi",
    "gyo",
    "gyu",
    "ha",
    "he",
    "hi",
    "ho",
    "hu",
    "hya",
    "hye",
    "hyi",
    "hyo",
    "hyu",
    "i",
    "ja",
    "je",
    "ji",
    "jo",
    "ju",
    "jya",
    "jye",
    "jyi",
    "jyo",
    "jyu",
    "ka",
    "ke",
    "ki",
    "ko",
    "ku",
    "kwa",
    "kya",
    "kye",
    "kyi",
    "kyo",
    "kyu",
    "la",
    "le",
    "li",
    "lka",
    "lke",
    "lo",
    "ltu",
    "lu",
    "lwa",
    "lya",
    "lye",
    "lyi",
    "lyo",
    "lyu",
    "ma",
    "mba",
    "mbe",
    "mbi",
    "mbo",
    "mbu",
    "me",
    "mi",
    "mma",
    "mme",
    "mmi",
    "mmo",
    "mmu",
    "mo",
    "mpa",
    "mpe",
    "mpi",
    "mpo",
    "mpu",
    "mu",
    "mya",
    "mye",
    "myi",
    "myo",
    "myu",
    "n'",
    "na",
    "ne",
    "ni",
    "nn",
    "no",
    "nu",
    "nya",
    "nye",
    "nyi",
    "nyo",
    "nyu",
    "o",
    "pa",
    "pe",
    "pi",
    "po",
    "pu",
    "pya",
    "pye",
    "pyi",
    "pyo",
    "pyu",
    "qa",
    "qe",
    "qi",
    "qo",
    "qu",
    "qwa",
    "qwe",
    "qwi",
    "qwo",
    "qwu",
    "qya",
    "qye",
    "qyi",
    "qyo",
    "qyu",
    "ra",
    "re",
    "ri",
    "ro",
    "ru",
    "rya",
    "rye",
    "ryi",
    "ryo",
    "ryu",
    "sa",
    "se",
    "sha",
    "she",
    "shi",
    "sho",
    "shu",
    "si",
    "so",
    "su",
    "swa",
    "swe",
    "swi",
    "swo",
    "swu",
    "sya",
    "sye",
    "syi",
    "syo",
    "syu",
    "ta",
    "tcha",
    "tche",
    "tchi",
    "tcho",
    "tchu",
    "te",
    "tha",
    "the",
    "thi",
    "tho",
    "thu",
    "ti",
    "to",
    "tsa",
    "tse",
    "tsi",
    "tso",
    "tsu",
    "tu",
    "twa",
    "twe",
    "twi",
    "two",
    "twu",
    "tya",
    "tye",
    "tyi",
    "tyo",
    "tyu",
    "u",
    "va",
    "ve",
    "vi",
    "vo",
    "vu",
    "vya",
    "vye",
    "vyi",
    "vyo",
    "vyu",
    "wa",
    "we",
    "wi",
    "wo",
    "wu",
    "xa",
    "xe",
    "xi",
    "xka",
    "xke",
    "xn",
    "xo",
    "xtu",
    "xu",
    "xwa",
    "xya",
    "xye",
    "xyi",
    "xyo",
    "xyu",
    "ya",
    "ye",
    "yi",
    "yo",
    "yu",
    "za",
    "ze",
    "zi",
    "zo",
    "zu"]

ROMAJI_VALUES: List[str] = [
    "ー",
    "～",
    "あ",
    "ば",
    "べ",
    "び",
    "ぼ",
    "ぶ",
    "びゃ",
    "びぇ",
    "びぃ",
    "びょ",
    "びゅ",
    "か",
    "せ",
    "ちゃ",
    "ちぇ",
    "ち",
    "ちょ",
    "ちゅ",
    "し",
    "こ",
    "く",
    "だ",
    "で",
    "でゃ",
    "でぇ",
    "でぃ",
    "でょ",
    "でゅ",
    "ぢ",
    "ど",
    "づ",
    "え",
    "ふぁ",
    "ふぇ",
    "ふぃ",
    "ふぉ",
    "ふ",
    "ふぁ",
    "ふぇ",
    "ふぃ",
    "ふぉ",
    "ふぅ",
    "ふゃ",
    "ふぇ",
    "ふぃ",
    "ふょ",
    "ふゅ",
    "が",
    "げ",
    "ぎ",
    "ご",
    "ぐ",
    "ぐぁ",
    "ぐぇ",
    "ぐぃ",
    "ぐぉ",
    "ぐぅ",
    "ぎゃ",
    "ぎぇ",
    "ぎぃ",
    "ぎょ",
    "ぎゅ",
    "は",
    "へ",
    "ひ",
    "ほ",
    "ふ",
    "ひゃ",
    "ひぇ",
    "ひぃ",
    "ひょ",
    "ひゅ",
    "い",
    "じゃ",
    "じぇ",
    "じ",
    "じょ",
    "じゅ",
    "じゃ",
    "じぇ",
    "じぃ",
    "じょ",
    "じゅ",
    "か",
    "け",
    "き",
    "こ",
    "く",
    "くぁ",
    "きゃ",
    "きぇ",
    "きぃ",
    "きょ",
    "きゅ",
    "ぁ",
    "ぇ",
    "ぃ",
    "ヵ",
    "ヶ",
    "ぉ",
    "っ",
    "ぅ",
    "ゎ",
    "ゃ",
    "ぇ",
    "ぃ",
    "ょ",
    "ゅ",
    "ま",
    "んば",
    "んべ",
    "んび",
    "んぼ",
    "んぶ",
    "め",
    "み",
    "んま",
    "んめ",
    "んみ",
    "んも",
    "んむ",
    "も",
    "んぱ",
    "んぺ",
    "んぴ",
    "んぽ",
    "んぷ",
    "む",
    "みゃ",
    "みぇ",
    "みぃ",
    "みょ",
    "みゅ",
    "ん",
    "な",
    "ね",
    "に",
    "ん",
    "の",
    "ぬ",
    "にゃ",
    "にぇ",
    "にぃ",
    "にょ",
    "にゅ",
    "お",
    "ぱ",
    "ぺ",
    "ぴ",
    "ぽ",
    "ぷ",
    "ぴゃ",
    "ぴぇ",
    "ぴぃ",
    "ぴょ",
    "ぴゅ",
    "くぁ",
    "くぇ",
    "くぃ",
    "くぉ",
    "く",
    "くぁ",
    "くぇ",
    "くぃ",
    "くぉ",
    "くぅ",
    "くゃ",
    "くぇ",
    "くぃ",
    "くょ",
    "くゅ",
    "ら",
    "れ",
    "り",
    "ろ",
    "る",
    "りゃ",
    "りぇ",
    "りぃ",
    "りょ",
    "りゅ",
    "さ",
    "せ",
    "しゃ",
    "しぇ",
    "し",
    "しょ",
    "しゅ",
    "し",
    "そ",
    "す",
    "すぁ",
    "すぇ",
    "すぃ",
    "すぉ",
    "すぅ",
    "しゃ",
    "しぇ",
    "しぃ",
    "しょ",
    "しゅ",
    "た",
    "っちゃ",
    "っちぇ",
    "っち",
    "っちょ",
    "っちゅ",
    "て",
    "てゃ",
    "てぇ",
    "てぃ",
    "てょ",
    "てゅ",
    "ち",
    "と",
    "つぁ",
    "つぇ",
    "つぃ",
    "つぉ",
    "つ",
    "つ",
    "とぁ",
    "とぇ",
    "とぃ",
    "とぉ",
    "とぅ",
    "ちゃ",
    "ちぇ",
    "ちぃ",
    "ちょ",
    "ちゅ",
    "う",
    "ヴぁ",
    "ヴぇ",
    "ヴぃ",
    "ヴぉ",
    "ヴ",
    "ヴゃ",
    "ヴぇ",
    "ヴぃ",
    "ヴょ",
    "ヴゅ",
    "わ",
    "ゑ",
    "ゐ",
    "を",
    "う",
    "ぁ",
    "ぇ",
    "ぃ",
    "ヵ",
    "ヶ",
    "ん",
    "ぉ",
    "っ",
    "ぅ",
    "ゎ",
    "ゃ",
    "ぇ",
    "ぃ",
    "ょ",
    "ゅ",
    "や",
    "いぇ",
    "い",
    "よ",
    "ゆ",
    "ざ",
    "ぜ",
    "じ",
    "ぞ",
    "ず",
]
