メインコンテンツへスキップ
見出し画像

【擬似言語⑤課題3❷】最頻値 | 方式❷ソート後に数える(基本情報技術者, 科目B, アルゴリズム)

    このNoteでは「最頻値」を求める擬似言語を作ります。

    3つ方式を考えついたので全3回になります。分かり易い回から学習しても大丈夫ですよ。ご自分でも「{1, 2, 4, 2}って4枚のカードが1枚ずつ手元に来た時に、一番枚数の多い数字をどう調べるか」手順を考えて見てくださいね。

    1つめ。部屋を準備して入ってもらう感じ。データによっては空室も残ります。>【擬似言語⑤課題3❶】最頻値 | 方式❶binを準備して数えるNote

    画像

    今回。2つめ(このNote)。予め並べてから数える方式。>【擬似言語⑤課題3❷】最頻値 | 方式❷ソート後に数えるNote(今回)

    画像

    3つめ。都度部屋を追加しながら数える方式。私が手作業でやるならこの手順かなぁ。>【擬似言語⑤課題3❸】最頻値 | 方式❸リスト登録しながら数えるNote

    画像

    それでは始めましょう!


    >全Noteへのリンク(FE節)
    ※科目Aのテーマ別/科目B/旧FE午後など沢山作りました!


    方式2 | ソート後に数える

    今回の方式は、ソートしてから数えます。

    ”今数えてる値”が変わるまで数えて、変わったら数え直す感じ。

    画像

    下記が、ざっくりした思考の流れ。

    1. 「1だな。数えるぞ。1個。最初だから最頻値にしとこ」

    2. 「2に変わったな。数えるぞ。1, 2個。さっきより多いから最頻値にしとこ」

    3. 「4に変わったな。数えるぞ。1個。さっきより少ないから、関係ないね。」

    以上より、最も多いの2個の、2が最頻値。




    下準備 | ソート関数を活用するために

    要は「bubbleSortOptimizedGlobal()」と引数なしで、配列arrayを並べ替えするようにするってだけです。

    「事情」が気になったら、下記を読んでください。


    arrayを「大域」で宣言する必要があります。

    >【擬似言語⑫】バブルソートのNote にて、「bubbleSortOptimized(整数型の配列: array)」を並べ替えをする関数として作りました。

    今回呼び出して結果を受ける必要があります。しかし「配列を返り値にする/複数の返り値を返すのに、コツが要るのがほとんど」です。pythonならできるんですが…。C言語とか大変ですよ…。

    FE科目Bでも、配列/複数の値を返り値にするのは避けて「大域」宣言でしています。
    >擬似言語の教科書のNote㉚
    >【FEB】令和05年科目B問03のNote

    画像
    sort関数が大域配列dataを操作

    今回も、getModeSort関数と呼び出されるbubbleSortOptimized関数で、大域配列arrayを共通して使います。大域宣言は関数外で行うので、bubbleSortOptimized関数の引数でのarray宣言は不要になります。

    大域: 実数型の配列: array
    
    ○整数型: getModeSort()
      整数型: ~省略~
    
      // 1. バブルソートで整列させる
      bubbleSortOptimizedGlobal()
    
    ○bubbleSortOptimizedGlobal()
      / 配列arrayをバブルソートで並べ替えて上書き */

    関数名もbubbleSortOptimizedからbubbleSortOptimizedGlobalに変えました。Globalを追加しただけ。

    ※違和感を持った方だけお読みください。arrayをいつ入力(引数やファイル読み込み)は割愛させて下さい。別に記載ないmain関数がある感じでお願いします。このNoteはあくまで、アルゴリズムを考えよう/擬似い言語を考えてよう、を主目的にしてます。しっかり書いても、初学者さんが情報過多で混乱しちゃうし、プログラム言語によってまた色々アレンジ必要ですもんね。




    関数の仕様

    では、手順を具体的に擬似言語に書き出す準備をします。

    画像

    ❶ソートは「bubbleSortOptimizedGlobal()」を呼び出すだけでOK。

    ❷現在数えている値を変数「currentVal」に、個数を「currentCount」に記録。最頻値は「modeVal」に、個数を「modeCount」に記録。


    数えている値が変わったら、今まで数えていた値(currentVal)の個数(currentCount)が、暫定最頻値(modeVal)の個数(modeCount)より大きいか審査。
    大きければ、暫定最頻値と個数を更新して新王者に。大きくなければ王者ならず(何もしない)。

    重要なイベントは、数える値の変化。

    数えている値が変わったら、数える値(currentVal)をこれから数える値に変更、個数(currentCount)はにリセット(0か1かは要検討。アルゴリズムに依るので。)。

    でも1番目の値は「値が変わったら」は起きない。数える系(currentVal, currentCount)と暫定最頻値系(modeVal, modeCount)の初期化で対応かな。図の「初代」王者。

    以上。言葉で書きましたが、チンプンカンプンだったら、実力か考えが足りてないです。手順を理解して自分で組みに挑戦できるぐらいなら、文章で「ふんふんそうだね」と、割と共感できるはず。




    答え | ループカウンタを「1」開始

    では擬似言語を組んでみてください。

    まずは処理のブロックを作って、ループや分岐条件を立てて、簡単なデータでトレースして動作確認する流れ。

    ブロックは下記。

    • 数える値が変わってない時の数え上げ(count←count+1的な)

    • 数える値が変わった時の処理

      • 今まで数えた値を最頻値にするか/しないか

      • これから数えるための準備(変数のリセット)

    • 上記をループに組み込む

    • 1番目のデータはループ開始前orループ内で処理するか考える

    今回はループカウンタを「1」から始めたいので、1番目のデータ処理もループ内で行なってもツジツマが合うような初期値を、ループ前に行います(currentCount←0)。

     
     
    大学・専門学校の先生の解説Note。 学生時代にITパスポート試験・基本情報技術者試験・応用情報技術者試験を独学で高得点合格。情報処理安全確保支援士試験(セキスペ)・データベーススペシャリスト試験・ネットワークスペシャリスト試験・G検定なども取得。 2027年にPD-S受験予定。