Rustで競プロがやりたい(7)

Rustで灰Diffの問題を500問近く解いた。

500問解いたら流石に余裕と言いたいが、今でも詰まる要素が多々ある。 大体1分で解ける問題と、何かしらで詰まり10分、またはそれ以上かけてようやく解けるような問題がある。

しかし、Rustはそこまで難しくないとも思い始めている。

よく見るのが、変数に .() を付けまくっている書き方。 最初は呪文のように見えたが、冷静に見るとそうではないことが分かる。

例えば、下記コードでは文字列 X の 1 の数を数えている。

#[allow(non_snake_case)]
fn main() {
    let X = "000101".to_string();
    println!("{}", X.chars().filter(|&x| x == '1').count());
}

X を Chars 型にした後、filter で 1 文字ずつ 1 かどうかを確認し、最後に count で個数を返す。

もう一つ例を挙げる。

#[allow(non_snake_case)]
fn main() {
    let X = [1, 3, 2, 7, 9];
    println!("{}", X.iter().max().unwrap());
}

X の要素から、max で最大値を求め、Option 型で返されるので unwrap で値を取り出す。

つまり、「X を最終的にどうしたいか?」を考えて、必要であればそれを処理するために必要な処理を書き加えて...とすればいい。

あまりに長くなる場合や、処理ごとに分けて改行している人もいる。

#[allow(non_snake_case)]
fn main() {
    let X = [1, 3, 2, 7, 9];
    println!("{}", X.iter()
                        .max().unwrap());
}

ところで、通常は vec や array などは println! では出力できない。 下記のコードだとエラーが出てしまうが、それだとデバッグの際に困ってしまう。

#[allow(non_snake_case)]
fn main() {
    let X = [1, 3, 2, 7, 9];
    println!("{}", X);
}

しかし内部に :? を書くと、vec や array も出力できる。 これは Some(x) などの状態も出力できるのでかなり便利。

#[allow(non_snake_case)]
fn main() {
    let X = [1, 3, 2, 7, 9];
    println!("{:?}", X);
}

ちなみに、dbg! でも出力できる、dbg! の場合は何行目で出力したかも書かれるので見やすい。 しかし、デバッグ時にしか出力されないので、提出の際の出力として使うことはできない。

#[allow(non_snake_case)]
fn main() {
    let X = [1, 3, 2, 7, 9];
    dbg!(X);
}

変数を宣言する際、宣言する場所に気を付ける必要があった。 以下のコードでは、ans は -1 を出力する。

#[allow(non_snake_case)]
fn main() {
    let ans = "-1";
    if true {
        let ans = 99;
    }
    println!("{}", ans);
}

これは、if の中の ans は if のブロックを抜けたと同時に解放される為、なかったことになる。 いわゆるライフタイムというやつで、宣言する場所は大丈夫か、他の処理で回避できないかなど考える必要がたまにあった。

この処理をどうやってやればいいか分からないといったとき、普通は検索して調べるのだが、今はchatGPTを使う方法がある。 Rustでどういう処理をしたいかを聞くことで、コードまで書いて返してくれる。

この手法はかなり便利だが、質問の仕方や内容によっては頓珍漢な回答をされるので、参考程度にするとよい。

Rust は分かってくると楽しいが、灰Diffなのでまだ struct や impl の段階に行ってないし、そもそも参照で呼ぶべきなのか分からなかったり、*&x などという頓珍漢な参照が出てきたり。 環境面に関しても、デバッグビルドやリリースビルドなどは一切分からず、最終目標であるビジュアライザを作る辺りも一切手を付けれていない。

という状態でこれからも頑張る。