Rustで言語処理100本ノックしています。
第1章: 準備運動
今回は余裕があったので問題の要求より少し汎用性を持たせてみました。後編はこちら。
00. 文字列の逆順
文字列"stressed"の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.
一番最初の問題ですが、案外素直にいきませんでした...一度Chars
に変換してから逆順にし、String
に再変換して返しています。
pub fn reverse(text: &str) -> String {
text.chars().rev().collect()
}
01. 「パタトクカシーー」
「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.
前の問題ができていれば発想は同じなので簡単。Rustは結構functionalに書けますよね。
pub fn odd_chars(text: &str) -> String {
text.chars().step_by(2).collect()
}
02. 「パトカー」+「タクシー」=「パタトクカシーー」
「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.
これは意外とひねりが必要でした。
まずイテレータで交互に結合というのが無さそうなのと、char
型同士の簡単な演算で文字の結合としてできるものは有っても(format
マクロ等)そのたびにString
を生成するのでちょっと非効率かなと思い、バッファを用いる形にしてみました。
pub fn concat_alternately(left: &str, right: &str) -> String {
let mut result = String::new();
left.chars().zip(right.chars()).for_each(|(l, r)| {
result.push(l);
result.push(r);
});
result
}
03. 円周率
"Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.
単純に空白区切りで文字を数えるだけなら簡単なのですが、','
や'.'
を除こうとすると、標準では正規表現が使えないのでほんのちょっとだけ手間を掛けなきゃいけないみたいです。
pub fn pi_from_text() -> Vec<usize> {
let text = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.";
text.replace(",", "").replace(".", "").split_whitespace().map(|s| s.len()).collect()
}
04. 元素記号
"Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭に2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.
文章にするために犠牲になったMgをどう扱うか迷いましたが、とりあえずそのままにしておきました。
考え方は円周率のときと同じですが、map
ではなくenumerate
からのfor_each
にして、HashMap
へ格納しています。また、問題文中の「○○番目」は1始まりなので注意が必要です。
pub fn element_symbols() -> HashMap<String, usize> {
let text = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.";
let mut result = HashMap::new();
text.replace(".", "").split_whitespace().enumerate().for_each(|(i, s)| {
let symbol = match i {
0 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 18 => s.get(0..1).unwrap(),
_ => s.get(0..2).unwrap()
};
result.insert(symbol.to_string(), i + 1);
});
result
}