Blog ブログ

アルゴリズムのコラムを読んでみて知ったこと

こんにちは、水瀧です。
今回は「珠玉のプログラミング」にある、2分探索のアルゴリズムについてのコラムを読んだのでそこで感じたものを書いてみます。
読んだ本:珠玉のプログラミング 本質を見抜いたアルゴリズムとデータ構造

キーワード:

  • 疑似コード
  • 不変な表明
  • ループ処理の検証
    • 関数の検証
      • 前提条件(事前条件)
      • 結果

    キーワードごとでそれぞれ書いていきます。

    ではどうぞ。

    疑似コード
    いきなりコードをかける人はもちろんいるとは思います。
    ですが、新しいロジックを組んだり、既存のプログラムを読むときに時折実践していることがあります。
    それは、とりあえずコードがかけないときは疑似コードでロジックの筋道を立てるようにすることです。
    この本のコラムでも最初にコードを書くのではなく、まずは疑似コードで書いていました。

    例えばこんな感じ。

    この疑似コード、たいていの日本人の場合、
    自然言語は日本語だと思うのでロジックを考える際に、
    「何をどうしたいか」「何がしたいか」を明確にできます。

    日本語が混ざっているだけで、「やりたいこと」が決まっていれば、
    ロジックが組めないという壁にぶつかりにくくなりますね。
    それと人にロジックを伝える時が一番効果抜群です。
    何がしたいのかを伝えるためのコードですからね。

    最初に疑似コードを書いた人、ありがとう。

    不変な表明
    ループの処理でループの最初から最後まで変わらない状態を「不変な表明」とコラム内で言われていました。
    まあ、ループ処理で「ある状態を保ち続けるべき事柄」を簡単な文章で書いたもの。
    という感じですかね。
    これが守られていないと、2回目以降のループで帰るだろう結果が保障されなくなってしまいます。
    どころか手続きの部分でも正しさが保障されなくなります。
    私の言葉で言うと、繰り返すための約束。といったところでしょうか。
    約束を守らないと見返りは得られない。どの世界でも共通のルールですね。

    ループ処理の検証
    ループ処理でロジックを組む際に気をつけることがあります。
    それはループが終わるたびに、不変な表明が常に成り立つように操作をする必要があるということです。
    2分探索でいうところの「探索する範囲内に目的とする値があること」です。
    さらに、ループを終了させるための変化表明もまた必要になります。
    これは、「次の探索範囲は前の範囲より小さくなければならない」ということです。
    この検証ではこれらの不変な表明と変化表明を守るように疑似コードを書きます。
    書いてみました。

    普段はここまで詳細に表明を気にしていなかったので、改めて表明を意識することで、
    自分で書いたロジックの正しさを検証できると実感しました。
    今まではほどんど頭の中だけで考えていたので表明を書くことの大事さに気づきました。
    頭の中で片付けていいのはわざわざ書く必要がなくなるくらい、
    もっと経験を積んでからなのかもしれないです。

    2分探索では範囲の中央値が目的の値かどうかを比較するので、
    同じ場合はその時点でループの終了と結果を返します。
    そうでなかった場合は範囲を狭めなければならないのですが、
    ここでも守るべきは不変な表明なので、中央より前ならば終点を、
    中央より後ろならば始点を変化させることで、
    不変な表明も変化表明も成立させる操作になります。

    検証をする際に不変な表明と変化表明を明確化し、ループの都度成立するかどうかを検査、
    目的を達成した場合はループを終了、達成しなかった場合は表明を守るように操作することでループ処理の検証ができます。

    関数の検証
    関数の検証では「前提条件」と「結果」がキーワードです。

    関数に何か値を渡して処理を行う場合に前提条件が守られていなければなりません。
    (この前提条件は「事前条件」ということもあります。)

    関数は、「この値を渡すから、XXXした結果をください」に応える「手続き」です。
    つまり、「値」に対する約束を関数は提示していて、
    それを守っていれば必ず正しい手続きで得られた結果を返すということです。

    約束を守らないまま手続きを行って何か結果が得られたとしても、
    それは正しい結果ではないし、関数の利用者も正しいのか間違っているのか判断できない場合があります。
    なので不変な表明として前提条件を検証することで、関数の中で行う手続きが間違っているのか、はたまた正しいのかを検証できます。

    この前提条件と結果という関係性はいわゆる「契約」となり、
    これを利用するプログラミングを「契約プログラミング」と言います。

    ちなみにですが、私は普段「必ず存在しているべきデータ」を利用する処理に
    データを渡す前に前提条件としてチェックすることが多いです。

    まとめ
    今回は改めて2分岐探索のアルゴリズムを復習するにあたり、契約プログラミングや、
    プログラムの検証での疑似コードの有用性など、
    アルゴリズムに特化したわけではない部分も、改めて勉強し直せました。

    疑似コードでの検証と同様に、契約による検証も、
    普段のプログラミングでも使うことの多いテクニックだと思うので、
    今までぼんやりとしか意識していなかった分、今日からでもしっかりと意識していこうと思います。


    採用情報

    クラウドクリエイティブスタジオではエンジニアの方を絶賛募集中です。
    皆さんとともに、是非!良きゲームを作っていきたいと思っております!