📔

本_プログラマの数学 第2版 を読んで為になったこと

2023/03/20に公開

はじめに

表題の本を読んだので、そこで感じたことを記載していこうと思います。

読書のきっかけ

現在勤めている会社にて、課題図書として推奨されている本の為、読んでみようと思ったことがそもそものきっかけではあります。

ただ、数ある課題書の中でも、今回この本を読もうと思ったきっかけは、プログラミングを書く土台を作りたい、と思ったことがきっかけです。

私は現在エンジニアになって2年ほど経ちます。
しかしながら、バリバリの文系卒→ブライダルで接客/営業をしていたため、理系的な知識が疎く、理解のスピードや、プログラミングを書くスピードが遅く感じております。
日々、淡々とこなすだけでは、このスピードは上がらないだろうな、、と思いながら過ごしていた中で、この本と出会い、日々のプログラミングをよりよく理解する為の基礎を身につけるために、この本を読んでみることを決意しました。

為になったこと

内容は1-8章まであるので、全てを振り返るのではなく、自身が為になってことを抜粋して書いていこうと思います。

再帰的な構造を見つけ出す

再帰的な構造を見つけ出すとは、自己参照的な構造を持つデータ構造や関数を特定することを指します。再帰的な構造は、同様の処理を再帰的に繰り返す必要がある場合に有用です。たとえば、リスト内のすべての要素を処理する場合、再帰的なアルゴリズムを使用して処理を繰り返すことができます。

なぜこの考えが必要か

コードをシンプルにする

再帰的な構造を利用することで、同様の処理を繰り返し行うことができるため、自身のコーディングの手間が減ります。

コードの可読性を向上させる

上記に加えて、自分以外の人がコードを読む場合にも、わかりやすいコードになります。

エラーの発見

再帰的なアルゴリズムを実装する場合、無限ループに陥る可能性があるため、適切な終了条件を設定することが重要です。再帰的な構造を見つけることで、必要な終了条件を特定し、エラーを防ぐことができます。

ハノイの塔

本書の中で、再帰的な構造を理解する為の例としていくつか挙げられていますが、その中の一つであるハノイの塔について取り上げていきます。

ハノイの塔は、数学パズルの1つで、3本の棒と、最初に1つの棒に積まれた異なるサイズの円盤からなります。円盤は大きいものから小さいものの順に積まれており、目的は、すべての円盤を最初の棒から最後の棒に移動することです。ただし、1度に1枚の円盤しか動かすことができず、小さな円盤が大きな円盤の上に置かれることはできません。

このアルゴリズムは、円盤の数が増えるについて、より多くの再起的呼び出しが必要になります。
この再帰的な構造を捉えずにコーディングすると膨大なコードになりますが、再起的な構造を捉えると、下記のようなコードになります。

function hanoi($n, $from, $to, $via) {
    if($n == 1) {
        echo "Move disk 1 from $from to $to\n";
    }
    else {
        hanoi($n - 1, $from, $via, $to);
        echo "Move disk $n from $from to $to\n";
        hanoi($n - 1, $via, $to, $from);
    }
}

// 3つの円盤を最初の杭から最後の杭に移す例
hanoi(3, 'A', 'C', 'B');

指数的な爆発を考える

「指数的な爆発」という用語は、何かが指数関数的に増加していく現象を指しています。指数関数は、ベースとなる数を何乗かすることで求められる数列や関数であり、例えば2の指数関数は2のべき乗で表される数列や関数です。指数関数的な増加は非常に急速であり、指数が大きくなるにつれて増加のスピードはより急速になります。

本書の中の一例として、1mmの紙を39回だけおることで、地球から月の距離が分の那賀を作れてしまうことは驚きでした。

なぜこの考えが必要か

今までに、DBへのクエリが多く発生するケースがあり、よくよく紐解いてみると、指数的な爆発によって、数が多くなっていたというケースもありました。

指数関数的な爆発を考える必要は、その増加のスピードが非常に急速であるため、状況を制御不能にしてしまう可能性があるためです。

指数的な爆発は、状況によっては望ましいものではなく、制御不能な状態に陥ることもあります。そのため、指数関数的な増加が予測される状況では、早めに対策を講じることが重要です。

大事なこと

問題を解くときには、目の前にある問題のパターンを見抜き、一般化することが大切であることに再度気付かされました。一般化することで、今見えている問題以外にも適用できるようになります。「その問題にしか適用できないのであれば、それは解法の名には値しない」ということも身に染みて理解している今日この頃です。

また、プログラミングの成り立ちとして、「人間は複雑なことが苦手である」という根本があり、それを解決するために、論理が生まれ、グループ分けをしていくことでわかりやすく理解するようになった、ということも理解することで、プログラムをより理解しやすくなりました。

Discussion