Perlがくしゅう帳(Rubyも)

プログラミングの勉強会の参加記録や学んだことなど。 twitter ID : @tomcha_で活動しています。 最近は主にPerl関連の勉強会やコミュニティに参加しています。移転前のブログはこちら->http://ruby.doorblog.jp/

Perlで色々なアルゴリズムを実装してみた その2

アルゴリズムの実装力を養成するため、Perlで書いてみましたの続編です。

こちらの本の第8章から

図解入門よくわかるアルゴリズムの基本と仕組み (How‐nual Visual Guide Book)

図解入門よくわかるアルゴリズムの基本と仕組み (How‐nual Visual Guide Book)

再帰(第8章)

再帰アルゴリズムとは、その関数が目的を達成するまで、自分自身を何度も呼び出す構造となっている面白い構造です。
自分自身を深く深く掘り下げて、到達点に達した途端にすべてが解決するという、ピタゴラスイッチ的な面白い仕組みでとても好きなアルゴリズムです。
が、この「どう自分自身を掘り下げる(関数を呼び出す)か」「解決の到達点は何なのか」の勘所がなかなか難しいアルゴリズムでもあります。

最大公約数を求めるコード

2つの数の最大公約数を求める方法にユークリッドの互除法という方法があるそうです。2つの数を互いに割り算していくと答えが出る方法です。
その方法の理解はまだ出来ていませんが、とりあえずその仕組みを再帰で実装してみました。
「何度も割り算をしていく」が自分自身を掘り下げる関数に、「余りが0になった時」が解決の到達点っぽいですね。

最大公約数をユークリッドの互除法を使って再帰で実装する

階乗を求める

1からある数まで、1ずつ増やした数を掛け算した答えをだす(1 * 2 * 3 * ... * n)問題です。
掛けていく数を1ずつ増やすより、逆にnから1ずつ減らしていって最後に1になった時を解決の到達点と考えるのがポイントです。

階乗を求める

クイックソート

クイックソートは並べ替えのアルゴリズムの1つです。並べ替える元データから任意の1つの値を取り出し、その値より大きいグループと小さいグループの2つのグループに分け、出来たグループでまた同じ動作をしていきます。各グループの要素数はだんだん少なくなっていき、グループ分けが出来なくなるまで少なくなればそこが到達点 と考えます。
まずは自分なりに考えてたコードです。問題点は、グループ分けした要素(配列)を量産しているので、実行時のメモリを沢山使っているところです。

クイックソート1

クイックソートその2

本の実装例では、その1の問題点を見事に解決(新しい配列を量産するのではなく、元の配列内の数値をうまいこと入れ替えることで実装)していたので、その考え方で実装してみました。
配列の値をコピーするのではなく、元の配列の値の場所を入れ替える・・・そう、リファレンスの出番ですね。

クイックソートその2

ニュートン法

微分を使って平方根の値(近似値)を求める方法です。
ニュートン法自体の理解は数学的素養が必要なので、最近通っている高校数学勉強会での知識で、なんとなく分かった様な気がしている状態ですが、理屈の実装自体は難しくありません。

ニュートン法

台形法

ある関数(数学の)で書かれたグラフの面積を、定積分を使って求める方法です。
ニュートン法と同様、数学的素養が必要ですが、理屈の実装自体は難しくありません。

台形法

ダイクストラ

経路探索のアルゴリズム駅すぱあとみたいなやつですね。
自力ではさっぱり分からなかったので解説を読んで実装しました。すべての点の最短経路を求めるていき、その点がゴールなら解決するというアルゴリズムです。

ダイクストラ法

色々な基本アルゴリズムを実装してみましたが、このあたり全てがヒントなしでスラスラ書けるようになれたらなぁと思います。
まだ難しいアルゴリズムはすぐに忘れてしまいそうになるので、精進あるのみです。