TRPLの数当てゲーム
scalaを書き直したので同じ感じでrustで書けないか試す。
ループを使わずに書くとどうなるか。
恥ずかしいけど載せる。
最初かいたのはこれ
extern crate rand;
use std::io;
use std::cmp::Ordering;
use rand::Rng;
struct Gen<F>{
f:F
}
impl<R,F:FnMut()->R> Iterator for Gen<F>{
type Item=R;
fn next(&mut self)->Option<R> { Some((self.f)()) }
}
fn main(){
let secret_number = rand::thread_rng().gen_range(1,101);
println!("秘密の数字は次の通り:{}",secret_number);
println!("数をあててごらん");
println!("ほら、予想を入力してね");
(Gen{f:||{
let mut guess = String::new();
match io::stdin().read_line(&mut guess){
Err(s) => Err(s),
Ok(_) => Ok(guess)
}
}
})
.flat_map(|r| r.map(|s| s.trim().parse::<u32>()))
.filter(|r| r.is_ok())
.map(|r| r.unwrap() )
.map(|u| match u.cmp(&secret_number){
Ordering::Less => {println!("ちいさすぎる") ; u },
Ordering::Greater => {println!("大き過ぎる") ; u },
Ordering::Equal => {println!("正解"); u }
})
.filter(|u| u == &secret_number)
.nth(0);
}
rustでクロージャをとってIteratorを返す方法がないかなーと調べたら
std::iter::repeat_with
が見つかったんだけどnightly-onlyだったのでやめ。
repeat_withをぱくってGenとして自作した。
https://qiita.com/ubnt_intrepid/items/df70da960b21b222d0ad
の最初の方だけ読んだけど、Python,C#,JavaScriptっぽいジェネレータ(yield)も入れようとしてるっぽい??
いつになるかはわからないけど。
で、、、とりあえず動かそうと思って書いたので見返すといろいろとアレだ。
まず、、、
let mut guess = String::new();
match io::stdin().read_line(&mut guess){
Err(s) => Err(s),
Ok(_) => Ok(guess)
}
この辺
やりたいのはOkのときにOk(guess)に変えたいだけ。
Errはほっといていい。
ならread_lineの結果をmapすりゃよくね?
となって以下に変えた。
(Gen{f:||{
let mut guess = String::new();
io::stdin().read_line(&mut guess).map(|_| guess)
}
})
うん。うごく。
あとなんとなく不安でGen{...}を()で囲ってる。
その後.flat_mapて書いてOKなのかわからなかったからとりあえず書いていた。
(Gen{f:||{
let mut guess = String::new();
io::stdin().read_line(&mut guess).map(|_| guess)
}
})
.flat_map(|r| r.map(|s| s.trim().parse::<u32>()))
これも消してみる。
Gen{f:||{
let mut guess = String::new();
io::stdin().read_line(&mut guess).map(|_| guess)
}
}
.flat_map(|r| r.map(|s| s.trim().parse::<u32>()))
いけるっぽい。
次。
Gen{f:||{
let mut guess = String::new();
io::stdin().read_line(&mut guess).map(|_| guess)
}
}
.flat_map(|r| r.map(|s| s.trim().parse::<u32>()))
.filter(|r| r.is_ok())
なんかきもい。自分で穴掘って埋めてる感ある。
うーん。うまく言語化できない。
というかちゃんとダメなところが明確でないんだろうな。
考える。
んー。
だめ。時間切れ。
とりあえず以下になおした。
flat_map(|r| r)はflattenがnightlyだったから。
extern crate rand;
use std::io;
use std::cmp::Ordering;
use rand::Rng;
struct Gen<F>{
f:F
}
impl<R,F:FnMut()->R> Iterator for Gen<F>{
type Item=R;
fn next(&mut self)->Option<R> { Some((self.f)()) }
}
fn main(){
let secret_number = rand::thread_rng().gen_range(1,101);
println!("秘密の数字は次の通り:{}",secret_number);
println!("数をあててごらん");
println!("ほら、予想を入力してね");
Gen{f:||{
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.map(|_| guess)
.map(|s| s.trim().parse::<u32>())
}
}
.flat_map(|r| r)
.filter(|r| r.is_ok())
.map(|r| r.unwrap() )
.map(|u| match u.cmp(&secret_number){
Ordering::Less => {println!("ちいさすぎる") ; u },
Ordering::Greater => {println!("大き過ぎる") ; u },
Ordering::Equal => {println!("正解"); u }
})
.filter(|u| u == &secret_number)
.nth(0);
}