以下の内容はhttps://ngtkana.hatenablog.com/entry/2026/03/07/200646より取得しました。


Rust の Either でグリッド上の zig-zag 経路を生成する簡単な方法

競技プログラミングで、↓ みたいな形の経路を生成したくなることはありませんでしょうか。

─────┐
┌────┘
└────┐
┌────┘
└─────

みなさま「あります。」

出題例「これです。 https://atcoder.jp/contests/abc069/tasks/arc080_b

方法 1(推奨): Either を使う(外部ライブラリ)

Either はなんと、Iterator を実装しています。便利ですね。

このライブラリ他にも細かいトレイトやメソッドが豊富に整備されていて、至れり尽くせり、正直なめていました。

for (i, j) in (0..h).flat_map(|i| {
    match i % 2 {
        0 => Either::Left(0..w),
        1 => Either::Right((0..w).rev()),
        _ => unreachable!(),
    }
    .map(move |j| (i, j))
}) {
    println!("{i} {j}");
}

方法 2: 変数変換をする

競プロっぽくて(?)よいという説もあります。とはいえ個人的には

  • やりたいことそのものをそのまま書いた感じではないので読みにくいですし、間違いの温床でしょう
  • 今回偶々長さも同じですし、単純な変換をするだけで済みましたけれども、一般のイテレータではそうはいきませんよね

という理由で、ドストレートではないかなという気持ちです。

for (i, j) in (0..h).flat_map(|i| {
    (0..w).map(move |j| match i % 2 {
        0 => (i, j),
        1 => (i, w - 1 - j),
        _ => unreachable!(),
    })
}) {
    println!("{i} {j}");
}

方法 3: Box を使う

当然余計なメモリ確保は走りますが、見た目もシンタックスがゴツいことを除けばやりたいことそのままって感じですし、案外悪くないでしょうという気持ちはあります。

for (i, j) in (0..h).flat_map(|i| {
    let js: Box<dyn Iterator<Item = usize>> = match i % 2 {
        0 => Box::new(0..w),
        1 => Box::new((0..w).rev()),
        _ => unreachable!(),
    };
    js.map(move |j| (i, j))
}) {
    println!("{i} {j}");
}

どちらの方がマシかわかりませんが、最初のアームに as を書くという方法もあります。

for (i, j) in (0..h).flat_map(|i| {
    match i % 2 {
        0 => Box::new(0..w) as Box<dyn Iterator<Item = usize>>,
        1 => Box::new((0..w).rev()),
        _ => unreachable!(),
    }
    .map(move |j| (i, j))
}) {
    println!("{i} {j}");
}



以上の内容はhttps://ngtkana.hatenablog.com/entry/2026/03/07/200646より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14