目次
Rustで言語処理100本ノックのリファクタリングの続き。
前回はこちら。
とっくに終わってたのに、ブログ書いてなかった。。。
08. 暗号文
pub fn cipher(text: &str) -> String {
return String::from_iter(text.chars().map(|x| {
if x.is_ascii_alphanumeric() && x.is_lowercase() {
let mut b = [0; 4];
x.encode_utf8(&mut b);
b[0] = 219 - b[0];
char::from(b[0])
} else {
x
}
}));
}
Rustの文字列はUTF-8でエンコードされたテキストを保持しているので、文字コード自体は意識していないです。
chars()
でUnicodeスカラー値のイテレータが返ってくるので、1文字ずつ扱えるようになります。
ただ、1文字をバイトとして扱うのに手こずりました。
encode_utf8
というメソッドを利用して1バイトだけ取り出して、計算するというのをやっています。
文字種の判別のメソッドが用意されているのは便利ですね。
なんかもうちょっとスマートにできないのかな?と思いつつ動いたのでこれになってます。
09. Typoglycemia
pub fn typoglycemia(text: &str) -> String {
return text
.split_whitespace()
.map(|word| {
if word.len() <= 4 {
word.to_string()
} else {
let original = word.chars().collect::<Vec<char>>();
let first = original.get(0).unwrap();
let last = original.last().unwrap();
let mut typo = original[1..original.len() - 1]
.iter()
.map(|x| x.clone())
.collect::<Vec<char>>();
let mut rng = thread_rng();
typo.shuffle(&mut rng);
let mut typo = String::from_iter(typo.iter());
typo.insert(0, first.clone());
typo.push(last.clone());
typo
}
})
.collect::<Vec<String>>()
.join(" ");
}
一応、1行で記述できたかな?
まずは、スペースで単語ごとに区切った後に、word
(単語)の長さによって、処理を分岐し、単語が5文字以上の場合にランダムに並び替えを行うというのをやっています。
文字単位で処理を行うために、chars()
で1文字ずつ取り出しています。
最初と最後の文字だけはそのままに、間の文字をランダムにシャッフルするというのをやるのに、もとのword
のスライスからコピーした文字列を作り出してから組み立て直すということをやっています。
コピーしないでゴニョゴニョする方法ってあるのかなぁ? 思いつかなかったので、結構泥臭い感じの実装になってしまいました。
まとめ
めんどくさいので、コードをGitHubのソースコードからではなく、ブログにコードスニペットとしてコピペしました。Hugoでいい感じにGitHubのコードスニペット表示するのないかなぁ?
ということで、2年越しで1章が終了しました。 2章もやらないとなぁ。
comments powered by Disqus
See Also by Hugo
- 第4章終了(言語処理100本ノック2020)
- 第3章終了(言語処理100本ノック2020)
- 第1章の03から06まで(言語処理100本ノック2020)
- 第2章の12から19まで(言語処理100本ノック2020)
- 第2章の10から11まで(言語処理100本ノック2020)