人 $1$ 、人 $2$ 、$\ldots$ 、人 $N$ と番号付けられた $N$ 人が、この順番で時計回りに円卓に座っています。 特に、時計回りで人 $N$ の次の位置には人 $1$ が座っています。 $i = 1, 2, \ldots, N$ について、人 $i$ の名前は $S_i$ 、年齢は $A_i$ です。 ここで、異なる $2$ 人が同じ名前や同じ年齢であることはありません。 年齢が最も小さい人を起点として、座っている位置の時計回りの順番で、$N$ 人全員の名前を出力してください。
略
$N$
$S_1$ $A_1$
$\vdots$
$S_N$ $A_N$
AtCoderならinput!
が使えます。
input! {
n: usize,
p: [(String, u32); n],
}
宣言とともに配列で受け取れて綺麗です。
とりあえず年齢が最も低い人のインデックスを取得したいです。 まずは多言語でもやるようにforループをiを0からnまで回してみます。
let mut min_age = p[0].1;
let mut min_age_index = 0;
for i in 0..n {
if p[i].1 < min_age {
min_age = p[i].1;
min_age_index = i;
}
}
p[i]
とアクセスしているのがなんだか野暮な感じがしますね。
emumerate
を使えばindexと要素を同時に得ることもできます。
let mut min_age = p[0].1;
let mut min_age_index = 0;
for (i, value) in p.iter().enumerate(){
if value.1 < min_age {
min_age = value.1;
min_age_index = i;
}
}
しかしrustではそもそもforループよりもイテレーションを使うことが推奨されています(参考)。
イテレーションでmin_age_index
を取得してみます。
let min_age_index = (0..n).min_by_key(|i| p[*i].1).unwrap();
min_by_keyによって引数に渡した関数の値が最も小さな要素をOptionalで得ることができます。
また引数の関数の型はFnMut(&T) -> K
となっており借用かつ暗黙的な参照外しはしてくれないかたち(参考)なので、参照外しをしてあげます。
あとはmin_age_index
から順番に名前を表示していけばOKです!
for i in 0..n {
println!("{}", p[(i + min_age_index) % n].0)
}
しかし、ここでもforループではなくイテレーションを使うことができます。
println!("{}", (0..n).map(|i| p[(i + min_age_index) % n].0.clone()).join("\n"));
戒めとしてclone()
しないとStringはコピーできないのでムーブしようとし、Vecotorの一部分だけムーブすることは許されていないのでコンパイルエラーとなってしまいます。
明示的にclone()
を呼び出すか、to_string()
を用いてstrに変換してやる必要があります。
use proconio::*;
use itertools::*;
fn main() {
input!{
n: usize,
p: [(String, usize); n]
}
let min_age_index = (0..n).min_by_key(|i| p[*i].1).unwrap();
println!("{}", (0..n).map(|i| p[(i + min_age_index)%n].0.clone()).join("\n"));
}
AC!