optimize ari2nasi

This commit is contained in:
Tokuhiro Matsuno
2023-01-15 00:54:21 +09:00
parent 629b8b5fbf
commit b1fad0e169
4 changed files with 322 additions and 23 deletions

View File

@ -1,6 +1,6 @@
#!/bin/bash
set -x
cargo build || { echo 'cannot build.' ; exit 1; }
cargo build --release || { echo 'cannot build.' ; exit 1; }
ibus restart
ibus engine akaza
tail -F ~/.ibus-akaza.log

View File

@ -43,7 +43,7 @@ mod tests {
config.dicts[0],
DictConfig {
path: "/usr/share/skk/SKK-JISYO.okinawa".to_string(),
encoding: "euc-jp".to_string(),
encoding: Some("euc-jp".to_string()),
dict_type: "skk".to_string()
}
);

View File

@ -212,7 +212,6 @@ impl BigramWordViterbiEngineBuilder {
"Loaded configuration in {}msec.",
t2.duration_since(t1).unwrap().as_millis()
);
// TODO 実際に辞書を使う処理を実装する
}
let segmenter = Segmenter::new(vec![

View File

@ -4,15 +4,325 @@ use anyhow::bail;
use crate::romkan::RomKanConverter;
// TODO remove
const BOIN: [char; 5] = ['a', 'i', 'u', 'e', 'o'];
pub struct Ari2Nasi {
romkan_converter: RomKanConverter,
boin_map: HashMap<char, &'static str>,
roman_map: HashMap<&'static str, &'static str>,
}
impl Ari2Nasi {
pub fn new(romkan_converter: RomKanConverter) -> Ari2Nasi {
Ari2Nasi { romkan_converter }
let boin_map = HashMap::from([
('a', ""),
('i', ""),
('u', ""),
('e', ""),
('o', ""),
]);
let roman_map = HashMap::from([
("xa", ""),
("a", ""),
("xi", ""),
("i", ""),
("xu", ""),
("u", ""),
("vu", "う゛"),
("va", "う゛ぁ"),
("vi", "う゛ぃ"),
("ve", "う゛ぇ"),
("vo", "う゛ぉ"),
("xe", ""),
("e", ""),
("xo", ""),
("o", ""),
("ka", ""),
("ga", ""),
("ki", ""),
("kya", "きゃ"),
("kyu", "きゅ"),
("kyo", "きょ"),
("gi", ""),
("gya", "ぎゃ"),
("gyu", "ぎゅ"),
("gyo", "ぎょ"),
("ku", ""),
("gu", ""),
("ke", ""),
("ge", ""),
("ko", ""),
("go", ""),
("sa", ""),
("za", ""),
("shi", ""),
("sha", "しゃ"),
("shu", "しゅ"),
("si", ""),
("sya", "しゃ"),
("syu", "しゅ"),
("sho", "しょ"),
("ji", ""),
("ja", "じゃ"),
("ju", "じゅ"),
("jo", "じょ"),
("syo", "しょ"),
("zi", ""),
("zya", "じゃ"),
("zyu", "じゅ"),
("zyo", "じょ"),
("su", ""),
("zu", ""),
("se", ""),
("ze", ""),
("so", ""),
("zo", ""),
("ta", ""),
("da", ""),
("chi", ""),
("cha", "ちゃ"),
("chu", "ちゅ"),
("ti", ""),
("tya", "ちゃ"),
("tyu", "ちゅ"),
("cho", "ちょ"),
("di", ""),
("dya", "ぢゃ"),
("dyu", "ぢゅ"),
("dyo", "ぢょ"),
("tyo", "ちょ"),
("xtsu", ""),
("xtu", ""),
("vvu", "っう゛"),
("vva", "っう゛ぁ"),
("vvi", "っう゛ぃ"),
("vve", "っう゛ぇ"),
("vvo", "っう゛ぉ"),
("kka", "っか"),
("gga", "っが"),
("kki", "っき"),
("kkya", "っきゃ"),
("kkyu", "っきゅ"),
("kkyo", "っきょ"),
("ggi", "っぎ"),
("ggya", "っぎゃ"),
("ggyu", "っぎゅ"),
("ggyo", "っぎょ"),
("kku", "っく"),
("ggu", "っぐ"),
("kke", "っけ"),
("gge", "っげ"),
("kko", "っこ"),
("ggo", "っご"),
("ssa", "っさ"),
("zza", "っざ"),
("sshi", "っし"),
("ssha", "っしゃ"),
("ssi", "っし"),
("ssya", "っしゃ"),
("sshu", "っしゅ"),
("ssho", "っしょ"),
("ssyu", "っしゅ"),
("ssyo", "っしょ"),
("jji", "っじ"),
("jja", "っじゃ"),
("jju", "っじゅ"),
("jjo", "っじょ"),
("zzi", "っじ"),
("zzya", "っじゃ"),
("zzyu", "っじゅ"),
("zzyo", "っじょ"),
("ssu", "っす"),
("zzu", "っず"),
("sse", "っせ"),
("zze", "っぜ"),
("sso", "っそ"),
("zzo", "っぞ"),
("tta", "った"),
("dda", "っだ"),
("cchi", "っち"),
("tti", "っち"),
("ccha", "っちゃ"),
("cchu", "っちゅ"),
("ccho", "っちょ"),
("ddi", "っぢ"),
("ttya", "っちゃ"),
("ttyu", "っちゅ"),
("ttyo", "っちょ"),
("ddya", "っぢゃ"),
("ddyu", "っぢゅ"),
("ddyo", "っぢょ"),
("ttsu", "っつ"),
("ttu", "っつ"),
("ddu", "っづ"),
("tte", "って"),
("dde", "っで"),
("tto", "っと"),
("ddo", "っど"),
("hha", "っは"),
("bba", "っば"),
("ppa", "っぱ"),
("hhi", "っひ"),
("hhya", "っひゃ"),
("hhyu", "っひゅ"),
("hhyo", "っひょ"),
("bbi", "っび"),
("bbya", "っびゃ"),
("bbyu", "っびゅ"),
("bbyo", "っびょ"),
("ppi", "っぴ"),
("ppya", "っぴゃ"),
("ppyu", "っぴゅ"),
("ppyo", "っぴょ"),
("ffu", "っふ"),
("hhu", "っふ"),
("ffa", "っふぁ"),
("ffi", "っふぃ"),
("ffe", "っふぇ"),
("ffo", "っふぉ"),
("bbu", "っぶ"),
("ppu", "っぷ"),
("hhe", "っへ"),
("bbe", "っべ"),
("ppe", "っぺ"),
("hho", "っほ"),
("bbo", "っぼ"),
("ppo", "っぽ"),
("yya", "っや"),
("yyu", "っゆ"),
("yyo", "っよ"),
("rra", "っら"),
("rri", "っり"),
("rrya", "っりゃ"),
("rryu", "っりゅ"),
("rryo", "っりょ"),
("rru", "っる"),
("rre", "っれ"),
("rro", "っろ"),
("tu", ""),
("tsu", ""),
("du", ""),
("te", ""),
("de", ""),
("to", ""),
("do", ""),
("na", ""),
("ni", ""),
("nya", "にゃ"),
("nyu", "にゅ"),
("nyo", "にょ"),
("nu", ""),
("ne", ""),
("no", ""),
("ha", ""),
("ba", ""),
("pa", ""),
("hi", ""),
("hya", "ひゃ"),
("hyu", "ひゅ"),
("hyo", "ひょ"),
("bi", ""),
("bya", "びゃ"),
("byu", "びゅ"),
("byo", "びょ"),
("pi", ""),
("pya", "ぴゃ"),
("pyu", "ぴゅ"),
("pyo", "ぴょ"),
("fu", ""),
("fa", "ふぁ"),
("fi", "ふぃ"),
("fe", "ふぇ"),
("fo", "ふぉ"),
("hu", ""),
("bu", ""),
("pu", ""),
("he", ""),
("be", ""),
("pe", ""),
("ho", ""),
("bo", ""),
("po", ""),
("ma", ""),
("mi", ""),
("mya", "みゃ"),
("myu", "みゅ"),
("myo", "みょ"),
("mu", ""),
("me", ""),
("mo", ""),
("xya", ""),
("ya", ""),
("xyu", ""),
("yu", ""),
("xyo", ""),
("yo", ""),
("ra", ""),
("ri", ""),
("rya", "りゃ"),
("ryu", "りゅ"),
("ryo", "りょ"),
("ru", ""),
("re", ""),
("ro", ""),
("xwa", ""),
("wa", ""),
("wo", ""),
("n", ""),
("n'", ""),
("nn", ""),
("dyi", "でぃ"),
("-", ""),
("che", "ちぇ"),
("tye", "ちぇ"),
("cche", "っちぇ"),
("ttye", "っちぇ"),
("je", "じぇ"),
("zye", "じぇ"),
("zzye", "っじぇ"),
("dha", "でゃ"),
("dhi", "でぃ"),
("dhu", "でゅ"),
("dhe", "でぇ"),
("dho", "でょ"),
("ddha", "っでゃ"),
("ddhi", "っでぃ"),
("ddhu", "っでゅ"),
("ddhe", "っでぇ"),
("ddho", "っでょ"),
("tha", "てゃ"),
("thi", "てぃ"),
("thu", "てゅ"),
("the", "てぇ"),
("tho", "てょ"),
("ttha", "ってゃ"),
("tthi", "ってぃ"),
("tthu", "ってゅ"),
("tthe", "ってぇ"),
("ttho", "ってょ"),
(".", ""),
(",", ""),
("[", ""),
("]", ""),
("z[", ""),
("z-", ""),
("z.", ""),
("z,", ""),
("zh", ""),
("zj", ""),
("zk", ""),
("zl", ""),
("z]", ""),
("z/", ""),
("wi", "うぃ"),
("we", "うぇ"),
]);
Ari2Nasi {
romkan_converter,
boin_map,
roman_map,
}
}
fn expand_okuri(
@ -24,35 +334,25 @@ impl Ari2Nasi {
bail!("kana is empty");
};
if last_char.is_ascii_alphabetic() {
if BOIN.contains(&last_char) {
if self.boin_map.contains_key(&last_char) {
// 母音の場合はそのまま平仮名に変換する。
// e.g. "a" → "あ"
let okuri = self
.romkan_converter
.to_hiragana(last_char.to_string().as_str());
let okuri = self.boin_map.get(&last_char).unwrap();
let yomi = &kana[0..kana.len() - last_char.len_utf8()];
let kanjis = kanjis
.iter()
.map(|f| f.to_string() + okuri.as_str())
.collect();
Ok(vec![(yomi.to_string() + okuri.as_str(), kanjis)])
let kanjis = kanjis.iter().map(|f| f.to_string() + *okuri).collect();
Ok(vec![(yomi.to_string() + okuri, kanjis)])
} else {
// 子音の場合は母音の組み合わせによって全パターンつくって返す。
let mut result: Vec<(String, Vec<String>)> = Vec::new();
let yomi_base = &kana[0..kana.len() - last_char.len_utf8()].to_string();
for b in BOIN {
let okuri = self
.romkan_converter
.to_hiragana((last_char.to_string() + b.to_string().as_str()).as_str());
if okuri.chars().filter(|c| c.is_ascii_alphabetic()).count() > 0 {
for boin in BOIN {
let Some(okuri) = self
.roman_map.get((last_char.to_string() + boin.to_string().as_str()).as_str()) else {
// "wu" のような、平仮名に変換できない不正なローマ字パターンを生成しているケースもある。
// そういう場合は、スキップ。
continue;
}
let kanjis = kanjis
.iter()
.map(|f| f.to_string() + okuri.as_str())
.collect();
};
let kanjis = kanjis.iter().map(|f| f.to_string() + okuri).collect();
result.push((yomi_base.to_string() + okuri.to_string().as_str(), kanjis));
}
Ok(result)