🐼

Rustのリスト操作練習問題集#1(初級編1)

に公開

Rustのリスト操作練習問題集

Rustのイテレータとコレクション操作を練習するための問題集です。

基本的にはiter操作と配列の操作だけで解けるようにしています。 テスト用のリストも載せてあります。そのままコピペで使えるようにしてあります。別解などありましたらコメントくださるとありがたいです。

問題1: 配列の基本

問題

  • 配列(長さ5以上)から最初と最後の要素を取り出す。
  • 入力: input: &[i32](例: [10,20,30,40,50]
  • 出力: (i32, i32)(例: (10, 50)

テンプレートとテスト

fn solution(input: &[i32]) -> (i32, i32) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[10, 20, 30, 40, 50]), (10, 50));
    assert_eq!(solution(&[1, 2, 3, 4, 5]), (1, 5));
    assert_eq!(solution(&[-5, 0, 5, 10, 15]), (-5, 15));
    assert_eq!(solution(&[100, 200, 300, 400, 500, 600]), (100, 600));
}
解答と解説
fn solution(input: &[i32]) -> (i32, i32) {
    (input[0], input[input.len() - 1])
}

fn main() {
    assert_eq!(solution(&[10, 20, 30, 40, 50]), (10, 50));
    assert_eq!(solution(&[1, 2, 3, 4, 5]), (1, 5));
    assert_eq!(solution(&[-5, 0, 5, 10, 15]), (-5, 15));
    assert_eq!(solution(&[100, 200, 300, 400, 500, 600]), (100, 600));
}
fn solution(input: &[i32]) -> (i32, i32) {
    let first = input.first().copied().unwrap();
    let last = input.iter().rev().next().copied().unwrap();
    (first, last)
}

fn main() {
    assert_eq!(solution(&[10, 20, 30, 40, 50]), (10, 50));
    assert_eq!(solution(&[1, 2, 3, 4, 5]), (1, 5));
    assert_eq!(solution(&[-5, 0, 5, 10, 15]), (-5, 15));
    assert_eq!(solution(&[100, 200, 300, 400, 500, 600]), (100, 600));
}
  • 配列は固定長。先頭は a[0]、末尾は a.len()-1
    端要素は first()/last()iter().rev().next() などのイテレータ経由でも取得可能。

問題2: get とインデックスの違い

問題

  • input.get(3)input.get(1) を安全に参照し、値(Option<i32>)を返す。
  • 入力: input: &[i32](例: [10,20,30]
  • 出力: (Option<i32>, Option<i32>)(例: (None, Some(20))

テンプレートとテスト

fn solution(input: &[i32]) -> (Option<i32>, Option<i32>) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[10, 20, 30]), (None, Some(20)));
    assert_eq!(solution(&[5]), (None, None));
    assert_eq!(solution(&[7, 8]), (None, Some(8)));
    assert_eq!(solution(&[9, 10, 11, 12]), (Some(12), Some(10)));
}
解答と解説
fn solution(input: &[i32]) -> (Option<i32>, Option<i32>) {
    let a = input.get(3).copied();
    let b = input.get(1).copied();
    (a, b)
}

fn main() {
    assert_eq!(solution(&[10, 20, 30]), (None, Some(20)));
}
fn solution(input: &[i32]) -> (Option<i32>, Option<i32>) {
    let picks = [3usize, 1usize]
        .iter()
        .map(|&i| input.get(i).copied())
        .collect::<Vec<_>>();
    (picks[0], picks[1])
}
  • getOption<&T>copied()Option<T> に。

問題3: スライスのソートと反転

問題

  • 可変スライスを降順に並べ替える(sortreverse)。
  • 入力: input: Vec<i32>(例: [4,1,3,2]
  • 出力: Vec<i32>(例: [4,3,2,1]

テンプレートとテスト

fn solution(mut input: Vec<i32>) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(vec![4, 1, 3, 2]), vec![4, 3, 2, 1]);
    assert_eq!(solution(vec![1]), vec![1]);
    assert_eq!(solution(vec![2, 2, 2]), vec![2, 2, 2]);
    assert_eq!(solution(vec![10, -1, 0]), vec![10, 0, -1]);
}
解答と解説
fn solution(mut input: Vec<i32>) -> Vec<i32> {
    let s: &mut [i32] = &mut input;
    s.sort();
    s.reverse();
    input
}

fn main() {
    assert_eq!(solution(vec![4, 1, 3, 2]), vec![4, 3, 2, 1]);
}
fn solution(mut input: Vec<i32>) -> Vec<i32> {
    // 逆順比較で降順に並べ替え
    input.sort_by(|a, b| b.cmp(a));
    input
}
  • 可変スライスに対して並べ替え操作が可能。
    比較関数を用いて sort_by(|a,b| b.cmp(a)) とすれば反転不要で降順にできる。

問題4: 借用規則の順序

問題

  • 不変参照で最初の要素を読み、その後で可変参照を取得して書き換える。
  • 入力: input: Vec<i32>(例: [1,2,3,4]
  • 出力: (i32, Vec<i32>)(例: (1, [100,2,3,4])

テンプレートとテスト

fn solution(mut input: Vec<i32>) -> (i32, Vec<i32>) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(vec![1, 2, 3, 4]), (1, vec![100, 2, 3, 4]));
    assert_eq!(solution(vec![9]), (9, vec![100]));
    assert_eq!(solution(vec![0,0]), (0, vec![100, 0]));
    assert_eq!(solution(vec![5,6,7]), (5, vec![100,6,7]));
}
解答と解説
fn solution(mut input: Vec<i32>) -> (i32, Vec<i32>) {
    let s = &input[..];
    let first = s[0];
    let m: &mut [i32] = &mut input;
    m[0] = 100;
    (first, input)
}

fn main() {
    assert_eq!(solution(vec![1, 2, 3, 4]), (1, vec![100, 2, 3, 4]));
}
  • 不変参照の使用が終わってから可変参照を作る。

問題5: 文字列 chars とカウント

問題

  • String/&strchars() から母音 a,e,i,o,u の個数を数える。
  • 入力: input: &str(例: "abracadabra"
  • 出力: usize(例: 6

テンプレートとテスト

fn solution(input: &str) -> usize {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution("abracadabra"), 6);
    assert_eq!(solution(""), 0);
    assert_eq!(solution("bcdfg"), 0);
    assert_eq!(solution("aAeEiIoOuU"), 10); // 大小区別なら5に変更
}
解答と解説
fn solution(input: &str) -> usize {
    input.chars()
        .filter(|&c| matches!(c, 'a' | 'e' | 'i' | 'o' | 'u'))
        .count()
}

fn main() {
    assert_eq!(solution("abracadabra"), 6);
}
  • chars() は Unicode スカラ値単位で走査。matches! で簡潔に判定。

初級問題(40題)

以下では、基本操作の定着を目的とした初級問題をフォーマットに沿って提示します。

初級1: 標準入力から整数1つを読み取り表示

問題

  • 標準入力から整数を1つ読み取り、そのまま出力する。
  • 入力: 標準入力から1行(例: 42
  • 出力: 整数(例: 42

テンプレートとテスト

use std::io::{self, Read};

fn solution(input: &str) -> String {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution("42\n"), "42");
    assert_eq!(solution("0\n"), "0");
    assert_eq!(solution("-7\n"), "-7");
    assert_eq!(solution("123456\n"), "123456");
}
解答と解説
use std::io::{self, Read};

fn solution(input: &str) -> String {
    let n: i64 = input.trim().parse().unwrap();
    n.to_string()
}

fn main() {
    // 実使用時は標準入力全体を読み取って渡す
    let mut buf = String::new();
    io::stdin().read_to_string(&mut buf).unwrap();
    print!("{}", solution(&buf));
}
use std::io::{self, Read};

fn solution(input: &str) -> String {
    input
        .lines()
        .take(1)
        .map(|s| s.trim().parse::<i64>().unwrap())
        .map(|n| format!("{}", n))
        .next()
        .unwrap_or_else(|| "".to_string())
}
  • 先頭行だけを lines().take(1) で取り出し、map(parse)map(format!(...)) を合成して最終文字列を得る。

初級2: スペース区切り整数の合計

問題

  • 1行のスペース区切り整数列の合計を求める。
  • 入力: 標準入力から1行(例: 1 2 3
  • 出力: 合計(例: 6

テンプレートとテスト

fn solution(input: &str) -> i64 {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution("1 2 3\n"), 6);
    assert_eq!(solution("-1 1\n"), 0);
    assert_eq!(solution("0\n"), 0);
    assert_eq!(solution("10 20 30 40\n"), 100);
}
解答と解説
fn solution(input: &str) -> i64 {
    input.split_whitespace().map(|s| s.parse::<i64>().unwrap()).sum()
}

fn main() {
    use std::io::{self, Read};
    let mut buf = String::new();
    io::stdin().read_to_string(&mut buf).unwrap();
    println!("{}", solution(&buf));
}
  • split_whitespacemap(parse)sum の基本パイプライン。

初級3: 配列の最小値・最大値

問題

  • スライスの最小値と最大値を求める。
  • 入力: input: &[i32]
  • 出力: (i32, i32)(最小, 最大)

テンプレートとテスト

fn solution(input: &[i32]) -> (i32, i32) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[3,1,4,1,5]), (1,5));
    assert_eq!(solution(&[0]), (0,0));
    assert_eq!(solution(&[-2,-3,-1]), (-3,-1));
    assert_eq!(solution(&[10,10,10]), (10,10));
}
解答と解説
fn solution(input: &[i32]) -> (i32, i32) {
    let min = *input.iter().min().unwrap();
    let max = *input.iter().max().unwrap();
    (min, max)
}

fn main() {
    println!("{:?}", solution(&[3,1,4,1,5]));
}
  • iter().min/maxOption<&T> を返すため参照外しが必要。

初級4: Vec生成とpush/extend

問題

  • 空Vecを作り、pushextend_from_slice[1,2,3,4] を構築。
  • 入力: なし
  • 出力: Vec<i32>

テンプレートとテスト

fn solution() -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(), vec![1,2,3,4]);
    assert_eq!(solution(), vec![1,2,3,4]);
    assert_eq!(solution(), vec![1,2,3,4]);
    assert_eq!(solution(), vec![1,2,3,4]);
}
解答と解説
fn solution() -> Vec<i32> {
    let mut v = Vec::new();
    v.push(1);
    v.extend_from_slice(&[2,3,4]);
    v
}

fn main() {
    println!("{:?}", solution());
}
  • 既存の基本問題3と同趣旨の短縮版。

初級5: スライス部分取得と長さ

問題

  • input[2..5] の長さと内容を返す。
  • 入力: input: &[i32]
  • 出力: (usize, Vec<i32>)

テンプレートとテスト

fn solution(input: &[i32]) -> (usize, Vec<i32>) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[0,1,2,3,4,5]), (3, vec![2,3,4]));
    assert_eq!(solution(&[10,11,12,13,14]), (3, vec![12,13,14]));
    assert_eq!(solution(&[-1,0,1,2,3]), (3, vec![1,2,3]));
    assert_eq!(solution(&[2,2,2,2,2]), (3, vec![2,2,2]));
}
解答と解説
fn solution(input: &[i32]) -> (usize, Vec<i32>) {
    let s = &input[2..5];
    (s.len(), s.to_vec())
}

fn main() {
    println!("{:?}", solution(&[0,1,2,3,4,5]));
}
  • 既存の基本問題2と同様。

初級6: iter().sum()で合計(所有権保持)

問題

  • スライスの合計を iter().sum() で求める。
  • 入力: input: &[i32]
  • 出力: i32

テンプレートとテスト

fn solution(input: &[i32]) -> i32 {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[3,4,5]), 12);
    assert_eq!(solution(&[]), 0);
    assert_eq!(solution(&[-1,-2,-3]), -6);
    assert_eq!(solution(&[100,200]), 300);
}
解答と解説
fn solution(input: &[i32]) -> i32 {
    input.iter().sum()
}
  • 既存の基本問題5と同様。

初級7: into_iter().mapで+1

問題

  • ベクトルを消費して各要素に+1したVecを返す。
  • 入力: input: Vec<i32>
  • 出力: Vec<i32>

テンプレートとテスト

fn solution(input: Vec<i32>) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(vec![1,2,3]), vec![2,3,4]);
    assert_eq!(solution(vec![]), Vec::<i32>::new());
    assert_eq!(solution(vec![-1,0]), vec![0,1]);
    assert_eq!(solution(vec![100]), vec![101]);
}
解答と解説
fn solution(input: Vec<i32>) -> Vec<i32> {
    input.into_iter().map(|x| x + 1).collect()
}
  • 既存の基本問題6と同様。

初級8: iter_mutで全要素を倍にする

問題

  • 可変ベクトルの全要素を2倍にして返す。
  • 入力: input: Vec<i32>
  • 出力: Vec<i32>

テンプレートとテスト

fn solution(mut input: Vec<i32>) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(vec![1,2,3]), vec![2,4,6]);
    assert_eq!(solution(vec![]), Vec::<i32>::new());
    assert_eq!(solution(vec![0,5]), vec![0,10]);
    assert_eq!(solution(vec![-1,-2]), vec![-2,-4]);
}
解答と解説
fn solution(mut input: Vec<i32>) -> Vec<i32> {
    for x in input.iter_mut() { *x *= 2; }
    input
}
  • iter_mut の基本操作。

初級9: windows(2)で増加箇所カウント

問題

  • windows(2)w[0] < w[1] の箇所数を数える。
  • 入力: input: &[i32]
  • 出力: usize

テンプレートとテスト

fn solution(input: &[i32]) -> usize {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[1,2,2,5,4,6]), 3);
    assert_eq!(solution(&[]), 0);
    assert_eq!(solution(&[3]), 0);
    assert_eq!(solution(&[5,4,3,2,1]), 0);
}
解答と解説
fn solution(input: &[i32]) -> usize {
    input.windows(2).filter(|w| w[0] < w[1]).count()
}
  • 既存の基本問題9と同様。

初級10: chunks(3)でチャンク部分和

問題

  • chunks(3) ごとに合計を計算し Vec<i32> を返す。
  • 入力: input: &[i32]
  • 出力: Vec<i32>

テンプレートとテスト

fn solution(input: &[i32]) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[1,2,3,4,5,6,7]), vec![6,15,7]);
    assert_eq!(solution(&[1,2,3]), vec![6]);
    assert_eq!(solution(&[1,2]), vec![3]);
    assert_eq!(solution(&[0,0,0,0,0,0]), vec![0,0]);
}
解答と解説
fn solution(input: &[i32]) -> Vec<i32> {
    input.chunks(3).map(|c| c.iter().sum()).collect()
}
  • 既存の基本問題10と同様。

初級11: split_atで左右合計

問題

  • split_at(4) で左右に分割し、それぞれの合計を返す。
  • 入力: input: &[i32]
  • 出力: (i32, i32)

テンプレートとテスト

fn solution(input: &[i32]) -> (i32, i32) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[1,2,3,4,5,6]), (10,11));
    assert_eq!(solution(&[0,0,0,0,1,1]), (0,2));
    assert_eq!(solution(&[10,10,10,10,10,10]), (40,20));
    assert_eq!(solution(&[-1,-2,-3,-4,5,6]), (-10,11));
}
解答と解説
fn solution(input: &[i32]) -> (i32, i32) {
    let (l, r) = input.split_at(4);
    (l.iter().sum(), r.iter().sum())
}
fn solution(input: &[i32]) -> (i32, i32) {
    // take/skip + sum のイテレータ合成でも書ける
    let left  = input.iter().take(4).copied().sum();
    let right = input.iter().skip(4).copied().sum();
    (left, right)
}
  • split_at に加え、take/skip を使って左右を分けてから sum() で集計する形もシンプル。

初級12: binary_searchで要素探索

問題

  • 昇順スライスで x=30 を探索、35 はNGとする。
  • 入力: input: &[i32]
  • 出力: (String, String)(30の結果, 35の結果)

テンプレートとテスト

fn solution(input: &[i32]) -> (String, String) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[10,20,30,40,50]), ("2".to_string(), "NG".to_string()));
    assert_eq!(solution(&[5,15,25]), ("NG".to_string(), "NG".to_string()));
    assert_eq!(solution(&[30]), ("0".to_string(), "NG".to_string()));
    assert_eq!(solution(&[5,10,15,20,25,30]), ("5".to_string(), "NG".to_string()));
}
解答と解説
fn solution(input: &[i32]) -> (String, String) {
    let r1 = match input.binary_search(&30) { Ok(i) => i.to_string(), Err(_) => "NG".to_string() };
    let r2 = match input.binary_search(&35) { Ok(i) => i.to_string(), Err(_) => "NG".to_string() };
    (r1, r2)
}
fn solution(input: &[i32]) -> (String, String) {
    let results: Vec<String> = [30, 35]
        .iter()
        .map(|&x| input.binary_search(&x).map(|i| format!("{}", i)).unwrap_or_else(|_| format!("{}", "NG")))
        .collect();
    (results[0].clone(), results[1].clone())
}
  • binary_searchResult<usize, usize> を返す。探索値を配列化して iter().map(...) で一括処理し、数値や文字列化は format!(...) で表現を揃えると読みやすい。

初級13: retainで偶数のみ

問題

  • 偶数のみ残し、先頭に0を入れて、インデックス2を削除。
  • 入力: input: Vec<i32>
  • 出力: Vec<i32>

テンプレートとテスト

fn solution(mut input: Vec<i32>) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(vec![1,2,3,4,5,6]), vec![0,2,4,6]);
    assert_eq!(solution(vec![2,4,6,8]), vec![0,2,6,8]);
    assert_eq!(solution(vec![0,1,2,3,4,5,6]), vec![0,0,2,4,6]);
    assert_eq!(solution(vec![10,11,12]), vec![0,10]);
}
解答と解説
fn solution(mut input: Vec<i32>) -> Vec<i32> {
    input.retain(|&x| x % 2 == 0);
    input.insert(0, 0);
    if input.len() > 2 { input.remove(2); }
    input
}
fn solution(input: Vec<i32>) -> Vec<i32> {
    let mut v: Vec<i32> = input.into_iter().filter(|&x| x % 2 == 0).collect();
    v.insert(0, 0);
    if v.len() > 2 { v.remove(2); }
    v
}
  • フィルタは into_iter().filter(|&x| ...)collect() で構築し、前置は insert(0, 0)、削除は remove(2) を合成で表現できる。

初級14: iter_mutで+10

問題

  • 全要素に10を加算して返す。
  • 入力: input: Vec<i32>
  • 出力: Vec<i32>

テンプレートとテスト

fn solution(mut input: Vec<i32>) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(vec![5,5,5]), vec![15,15,15]);
    assert_eq!(solution(vec![]), vec![] as Vec<i32>);
    assert_eq!(solution(vec![0]), vec![10]);
    assert_eq!(solution(vec![1,2,3,4]), vec![11,12,13,14]);
}
解答と解説
fn solution(mut input: Vec<i32>) -> Vec<i32> {
    for x in input.iter_mut() { *x += 10; }
    input
}
fn solution(input: Vec<i32>) -> Vec<i32> {
    input.into_iter().map(|x| x + 10).collect()
}
  • 変更を伴う更新も into_iter().map(|x| ..)collect() の合成で新しい Vec を作れる。

初級15: 端要素の取得 first/last

問題

  • スライスの先頭と末尾の要素を安全に取得(Option<i32>)。
  • 入力: input: &[i32]
  • 出力: (Option<i32>, Option<i32>)

テンプレートとテスト

fn solution(input: &[i32]) -> (Option<i32>, Option<i32>) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[1,2,3]), (Some(1), Some(3)));
    assert_eq!(solution(&[]), (None, None));
    assert_eq!(solution(&[10]), (Some(10), Some(10)));
    assert_eq!(solution(&[0,0]), (Some(0), Some(0)));
}
解答と解説
fn solution(input: &[i32]) -> (Option<i32>, Option<i32>) {
    (input.first().copied(), input.last().copied())
}
fn solution(input: &[i32]) -> (Option<i32>, Option<i32>) {
    let first = input.iter().next().copied();
    let last = input.iter().rev().next().copied();
    (first, last)
}
  • 末尾は iter().rev().next() でも取得可能で、copied()Option<i32> に変換できる。

初級16: 反転と回文判定

問題

  • ベクタを反転して回文かどうかを判定。
  • 入力: input: Vec<i32>
  • 出力: (Vec<i32>, bool)

テンプレートとテスト

fn solution(mut input: Vec<i32>) -> (Vec<i32>, bool) {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(vec![1,2,3,2,1]), (vec![1,2,3,2,1], true));
    assert_eq!(solution(vec![1,2,3]), (vec![3,2,1], false));
    assert_eq!(solution(vec![]), (vec![], true));
    assert_eq!(solution(vec![5,5]), (vec![5,5], true));
}
解答と解説
fn solution(mut input: Vec<i32>) -> (Vec<i32>, bool) {
    let rev = {
        let mut c = input.clone();
        c.reverse();
        c
    };
    let is_pal = input == rev;
    (rev, is_pal)
}
fn solution(input: Vec<i32>) -> (Vec<i32>, bool) {
    let rev: Vec<i32> = input.iter().cloned().rev().collect();
    let is_pal = input.iter().eq(input.iter().rev());
    (rev, is_pal)
}
  • 反転は iter().cloned().rev().collect()、回文判定は iter().eq(iter().rev()) の比較で書ける。

初級17: 昇順ソート(安定)

問題

  • ベクタを昇順に安定ソートする。
  • 入力: input: Vec<i32>
  • 出力: Vec<i32>

テンプレートとテスト

fn solution(mut input: Vec<i32>) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(vec![3,1,4,1,5]), vec![1,1,3,4,5]);
    assert_eq!(solution(vec![]), vec![] as Vec<i32>);
    assert_eq!(solution(vec![2,2,2]), vec![2,2,2]);
    assert_eq!(solution(vec![10,-1,0]), vec![-1,0,10]);
}
解答と解説
fn solution(mut input: Vec<i32>) -> Vec<i32> {
    input.sort();
    input
}
fn solution(mut input: Vec<i32>) -> Vec<i32> {
    input.sort_by_key(|&x| x);
    input
}
  • 安定ソートは sort_by_key(|&x| x) でも等価に書け、キー関数で並べ替え基準を柔軟に指定できる。

初級18: filterで正数のみ抽出

問題

  • スライスから正の整数のみを抽出して返す。
  • 入力: input: &[i32]
  • 出力: Vec<i32>

テンプレートとテスト

fn solution(input: &[i32]) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[-2,-1,0,1,2]), vec![1,2]);
    assert_eq!(solution(&[]), vec![] as Vec<i32>);
    assert_eq!(solution(&[0,0]), vec![] as Vec<i32>);
    assert_eq!(solution(&[5,10]), vec![5,10]);
}
解答と解説
fn solution(input: &[i32]) -> Vec<i32> {
    input.iter().cloned().filter(|&x| x > 0).collect()
}
fn solution(input: &[i32]) -> Vec<i32> {
    input.iter().copied().filter(|&x| x > 0).collect()
}
  • Copy な要素は cloned() の代わりに copied() を使うと意図が明確になる。

初級19: enumerateで添字つき走査

問題

  • (index, value) のペア列を作る。
  • 入力: input: &[i32]
  • 出力: Vec<(usize, i32)>

テンプレートとテスト

fn solution(input: &[i32]) -> Vec<(usize, i32)> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[10,20,30]), vec![(0,10),(1,20),(2,30)]);
    assert_eq!(solution(&[]), vec![] as Vec<(usize,i32)>);
    assert_eq!(solution(&[5]), vec![(0,5)]);
    assert_eq!(solution(&[7,7]), vec![(0,7),(1,7)]);
}
解答と解説
fn solution(input: &[i32]) -> Vec<(usize, i32)> {
    input.iter().cloned().enumerate().collect()
}
fn solution(input: &[i32]) -> Vec<(usize, i32)> {
    input.iter().enumerate().map(|(i, &v)| (i, v)).collect()
}
  • enumerate() 後に参照を値へは map(|(i,&v)| ...) で取り出す形でもよい。

初級20: zipで2配列の要素和

問題

  • 2つのスライスを対応要素で足し合わせる(短い方に合わせる)。
  • 入力: a: &[i32], b: &[i32]
  • 出力: Vec<i32>

テンプレートとテスト

fn solution(a: &[i32], b: &[i32]) -> Vec<i32> {
    // ここに解答
    unimplemented!()
}

fn main() {
    assert_eq!(solution(&[1,2,3], &[4,5,6]), vec![5,7,9]);
    assert_eq!(solution(&[1,2], &[10]), vec![11]);
    assert_eq!(solution(&[], &[]), vec![] as Vec<i32>);
    assert_eq!(solution(&[0,0,0], &[1,1,1,1]), vec![1,1,1]);
}
解答と解説
fn solution(a: &[i32], b: &[i32]) -> Vec<i32> {
    a.iter().zip(b.iter()).map(|(x,y)| x + y).collect()
}
fn solution(a: &[i32], b: &[i32]) -> Vec<i32> {
    a.iter().copied().zip(b.iter().copied()).map(|(x,y)| x + y).collect()
}
  • 参照のまま足す場合は x + y&i32 足しにならないように copied() で値へ落としておくと型が揃う。

Discussion