以下の内容はhttps://2323-code.hatenablog.com/entry/2025/09/13/232037より取得しました。


【Rust】基本情報B科目の擬似言語をRustで書き直してみたら楽しく学べて良い

結論

  • 擬似言語を実際書き直して動かすことで、値の動きを自分で見られる。
  • 書きながら処理の流れがわかるのでめちゃくちゃ楽しい。 (大事)
  • Rustの知らない書き方も知れた
  • Rustの良いリハビリにもなった

前提

  • 目的は「よくあるアルゴリズムに慣れること」
  • 筆者はバブルソートと二部探索、クイックソートくらいしか知らない
  • そしてそれらをどう実装するか知らない
  • 自分の好きな言語で実際に書いて、動かしてみることに。

擬似言語について

下記サイトで記述された擬似言語を元に、Rustで書き直しています。

www.seplus.jp

www.seplus.jp

≠を表現したい時

!= でOK

  • 実際擬似言語だと≠で表記されていて、咄嗟にRustで書けなかった
  • でも調べたらあっさり!=で良いことがわかった

擬似言語

引用元:

www.seplus.jp

整数型の配列: a ← { 12, 34, 56, 78, 90 }
整数型: sum ← 0
整数型: i ← 1
while (i ≦ 5)
  sum ← sum + a[i]
  i ← i + 1
endwhile
writeLine(sum)

Rustで書き直す

fn main() {
    sum();
}

fn sum() {
    let a = [12, 34, 56, 78, 90];
    let mut sum = 0;
    let mut i = 1;
    while i <= 5 {
        println!("{i}");
        println!("{sum}");
        println!("{}", a[i]);
        sum = sum + a[i];
        println!("{sum}");
        i += 1;
        println!("------");
    }
    println!("{sum}");
}

実行結果

1からnまで1つずつ増やす

  • ループでもstart..end(またはstart..=end)の書き方ができる!
  • もっというとループの時の変数は宣言しなくてもいい。

擬似言語

引用元:

www.seplus.jp

整数型: hour, minute
for (hour を 0 から 23 まで 1 ずつ増やす)     // 外側のループ
  for (minute を 0 から 59 まで 1 ずつ増やす) // 内側のループ
    hour 時 minute 分を表示する
  endfor
endfor

Rustで書き直す

fn main() {
    clock();
}

fn clock() {
    for hour in 0..=23 {
        for minute in 0..=59 {
            println!(" {hour} 時 {minute} 分です");
        }
    }
}

https://x.com/2323_code/status/1966789601097621639

実行結果

nから1ずつ減らす

ループの範囲を降順で行いたかったのですが、やり方がわからず苦戦しました。

擬似言語

出典: www.seplus.jp

整数型の配列: a ← { 78, 56, 34, 12 }
整数型: num, pos, temp
for (num を 1 から 3 まで 1 ずつ増やす)       // 外側のループ
  for (pos を 4 から num +1 まで 1 ずつ減らす)    // 内側のループ
    if (a[pos - 1] > a[pos])
      temp ← a[pos]
      a[pos] ← a[pos - 1]
      a[pos - 1] ← temp
    endif
  endfor
endfor

Rustで書き直す

今までのstart..endに合わせて下記のように書くと、コンパイルは通るものの、ソート後の値が変わりませんでした。

fn main() {
    bubble_sort();
}

fn bubble_sort() {
    let mut a = [78, 56, 34, 12];
    let mut temp: i32;
    println!("ソート前: {:?}", a);

    for num in 1..=3 {
        // for (num を 1 から 3 まで 1 ずつ増やす)
        for pos in 4..=num + 1 - 1 {
            //  for (pos を 4 から num +1 まで 1 ずつ減らす)
            if a[pos - 1] > a[pos] {
                temp = a[pos];
                a[pos] = a[pos - 1];
                a[pos - 1] = temp;
            }
        }
    }
    println!("ソート後: {:?}", a);
}

実行結果

擬似言語をもう一度読み返してみる

実現したいのはこの行。

  for (pos を 4 から num +1 まで 1 ずつ減らす)    // 内側のループ

分解してみると、

  • 変数 pos
  • 4からnum+1まで
  • 1つずつ減らす

つまり:num+1 の値になるまで、posから1ずつデクリメントしていきたい、ということのはず。

()で区切ったら行ける?

4..=num + 1 - 1としているせいで何も変化が起きなくなっているように感じたので、numに1インクリメントした値から-1したいよ、と伝えるためにかっこをつけてみます。

fn main() {
    bubble_sort();
}

fn bubble_sort() {
    let mut a = [78, 56, 34, 12];
    let mut temp: i32;
    println!("ソート前: {:?}", a);

    for num in 1..=3 {
        // for (num を 1 から 3 まで 1 ずつ増やす)
        for pos in 4..=(num + 1) - 1 { // かっこつけた
            //  for (pos を 4 から num +1 まで 1 ずつ減らす)
            if a[pos - 1] > a[pos] {
                temp = a[pos];
                a[pos] = a[pos - 1];
                a[pos - 1] = temp;
            }
        }
    }
    println!("ソート後: {:?}", a);
}

実行結果(変わりませんでした)

一緒だった。

1つずつデクリメントさせたい場合を調べてみる

「Rust ループ デクリメント」で検索しました。

結果下記の記事がヒットしたのでそれぞれ読んでみます。

magidropack.hatenablog.com

www.choge-blog.com

どうやらrangeの書き方(start...endの書き方)では降順にできないようです。

なので、(start..end).rev()のようにして、逆の順番にしてあげるのが良さそうです。

(start..end).rev()で実行:無事バブルソートができました!

  • rev()を使って逆順に
  • 添え字が0始まりなのに1からにしていたのも修正
    • 擬似言語だと1始まりだったのをそのままRustでやってしまいました
fn main() {
    bubble_sort();
}

fn bubble_sort() {
    let mut a = [78, 56, 34, 12];
    let mut temp: i32;
    println!("ソート前: {:?}", a);

    // for (num を 1 から 3 まで 1 ずつ増やす)
    for num in 0..3 {
        // 配列のインデックスが0始まりじゃなかった!!!!

        //  for (pos を 4 から num +1 まで 1 ずつ減らす)
        for pos in ((num + 1)..4).rev() {
            // 逆順にするには.rev()を使うぞ
            println!("pos: {pos}");
            println!("num: {num}");
            println!("a[pos - 1]: {}", a[pos - 1]);
            println!("a[pos]: {} ", a[pos]);

            if a[pos - 1] > a[pos] {
                temp = a[pos];
                a[pos] = a[pos - 1];
                a[pos - 1] = temp;
            }

            println!("-----");
        }
    }
    println!("ソート後: {:?}", a);
}

実行結果

ソート前: [78, 56, 34, 12]
pos: 3
num: 0
a[pos - 1]: 34
a[pos]: 12
-----
pos: 2
num: 0
a[pos - 1]: 56
a[pos]: 12
-----
pos: 1
num: 0
a[pos - 1]: 78
a[pos]: 12
-----
pos: 3
num: 1
a[pos - 1]: 56
a[pos]: 34
-----
pos: 2
num: 1
a[pos - 1]: 78
a[pos]: 34
-----
pos: 3
num: 2
a[pos - 1]: 78
a[pos]: 56
-----
ソート後: [12, 34, 56, 78]

擬似言語をRustで書き直してみた結果得られたもの

よくあるアルゴリズムの流れがより理解しやすい

地道にトレースをしても分からない(答えを出すまでが苦しい)のが、アルゴリズムを穴埋めするタイプの問題。

トレースしたら結果はわかるものの、正直その過程で正しいものを選べ、と言われたら全然分からなかった。

しかし、実際擬似言語のアルゴリズムをRustで書き直してみると、自分で書いているので「これはこう書くよな」「その後にこうくるよね」と流れがイメージしやすくなった。 侮れない。

自分で動かすから楽しい

動く!!楽しい〜〜!!!!!

正直これがすごく嬉しかったです。 正直科目Bの問題、本当に勉強が楽しく...なく...。

それはきっと私がよくあるアルゴリズムの構造を理解しておらず、もっと言えば自分で書いたことがないからイメージがつかない→結局ゴリ押しで勉強しても理解できない→楽しくない、となっていたんだと思います。

自分の好きな言語で、ローカルの環境で好きなだけ試して、動かして。

分からないところは自分で出力してみて。納得するまで遊んで学べる。

プログラミングが楽しくて仕方ない!と感じたのは久しぶりでした。

Rustもしばらく書けていなかったので、とても良いリハビリになりました。ありがたや。

トレースも大事、でも実際に自分でプログラムを手で書いてみるのも大事。

実際手で書いてみるだけでこんなにも面白くなるのかと、自分でも驚きました。

試験まであと10日なので、引き続き科目Bの擬似言語をRustで書くのは続けつつ、科目Aの模試も1日1回やっていきます。

絶対合格するぞ...!




以上の内容はhttps://2323-code.hatenablog.com/entry/2025/09/13/232037より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

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