abc002.contest.atcoder.jp
“The Rust Programming Language” の第二版を最終章除いて読み終わったので、Atcoderでぽちぽちコード書く練習してるんだけど、
API全然知らないのでもうわっかんな~い(へらへら)
ありがたい………
qiita.com
use std::io;
fn main() {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).unwrap();
let mut word = buffer.trim().to_string();
for ch in "aeiou".chars() {
word = word.split(ch).collect::<Vec<_>>().concat();
}
println!("{}", word);
}
効率的な文字の消し方が分からんかったので、各母音字でsplit
して集めてを繰り返すという微妙なやりかたをした。
調べてて気づいたが、collect::<Vec<_>>().concat()
でなく、collect::<String>()
にしたほうが賢いね。
collect
はFromIterator
トレイトのメソッドで、char
イテレータはString
にコレクトできるので。
というようなことを考えてると、for文消したくなるね。
use std::io;
fn main() {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).unwrap();
let word = buffer.trim().to_string();
let word = "aeiou".chars().fold(word, |w, c| w.split(c).collect::<String>());
println!("{}", word);
}
畳み込めばいいよね!ってことで畳み込んだ。
もう少し素朴なやりかた。contains
とString
のpush
をおぼえた。
use std::io;
fn main() {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).unwrap();
let mut word = String::new();
for c in buffer.trim().chars() {
if !['a', 'e', 'i', 'o', 'u'].contains(&c) {
word.push(c)
}
}
println!("{}", word);
}
&str
がchar
の配列なりスライスではないので、if !['a', 'e', 'i', 'o', 'u'].contains(&c)
と書かないといけないのがPythonマンのおかゆには厳しさがある。
if !"aeiou".chars().collect<Vec<_>>.contains(&c)
とすればいけるけど。もっと簡単な書き方あるのかな~。
と色々書いてて思いついたけど、filter
使えばいいのでは……?
use std::io;
fn main() {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).unwrap();
let word: String = buffer.trim()
.chars()
.filter(|c| !['a', 'e', 'i', 'o', 'u'].contains(&c))
.collect();
println!("{}", word);
}
やっぱイテレータ触るならチェーンやで……!といわんばかりのチェーン
単語を文字のイテレータにして、子音だけパスしてコレクト。リストの内包表記こそ使えないものの、それにいちばん近いのは今までの中ならこれかな?
Pythonでなら、多分こう書くもんな:
word = "".join([c for c in word if c not in "aeiou"])
print(word)
追記(2017/8/7/20:05):replace あるやんけ
use std::io;
fn main() {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).unwrap();
let word: String = buffer.trim()
.replace(&['a', 'e', 'i', 'o', 'u'][..], "");
println!("{}", word);
}
あれからstr
のこと調べてると、スライスとstr
で contains
, starts_with
, ends_with
, find
, split
系の引数が違うらしいことを知った。
str
では、要素1つの代わりにパターン(Pattern
トレイトを実装している型)を取るらしい:
&String
&[char]
char
FnMut(char) -> bool
&&str
&str
文字1文字はもちろんのこと、部分文字列やら、char.is_numeric
といった関数も与えれるので、結構柔軟にパターンが作れるらしい。
特に、&[char]
は論理和(って言い方であってんのか)なので便利…。
ちなみにおかゆは .replace(&['a', 'e', 'i', 'o', 'u'], "")
ってして「&[char; 5]
はダメっぷ~~~~ww」ってコンパイラに言われてキレてたんですけど、
ジェネリクスのトレイトバウンドの箇所では諸々の型強制(今回だとunsize coercion)が効かないの忘れてた(てへぺろ)
Coercions -
こういう場面で型強制効かないのって安全のため?なんだろうけど、トレイトバウンドに使うときに融通の効くトレイトを作るのって結構大変そうだね。