NatureOfCodeの遺伝的アルゴリズムをすこし関数型プログラミングのように実装

NatureOfCodeのサンプルは、初心者にもわかりやすいif文やfor文が使われている文法ですが、最近のモダンな言語はmap/reduceのように関数型プログラミングの文法やAPIを取り入れているので、JavaScriptでまずはfor文を使わない実装を試してみました。

実装する前は、for文をforEachやmapに置き換えるのは大変と考えていましたが、実際にやってみると特に大きな躓きはありませんでした。関数型プログラミングに対する否定的な先入観が大きかったようで、実践的なプログラミングで試してみてそれが大きな間違いだと気づきました。

また、以下を少し意識するだけで、此処の関数がテストしやすくなり実践的なプログラミングで関数型プログラミングの良さを感じられました。

  • メソッドチェーン
  • 小さな関数に分割していく
  • constキーワードによる変数の定数化

以前F#を勉強したときは、あくまでも関数型プログラミングの勉強で演習問題を解くだけだったのですが、新しいプログラミングを勉強した際には、まとめとして実践的なプログラミングを書くことも大切なのを痛感しました。

JavaScriptでバラ曲線Rose Curve Function

最近、Codepen.ioでいくつか三角関数を使ったコードを書いていました。三角関数を複数組み合わせると複雑な動きになるので、調べているうちにバラ曲線というものを知り、JavaScriptで実装してみました。また、日本語のwikipediaにはXY座標について書かれていませんが、英語版のwikipediaにはMATLABでコードを書いたときの方法が書かれていました。

 

https://en.wikipedia.org/wiki/Rose_(mathematics)

https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%A9%E6%9B%B2%E7%B7%9A

See the Pen Rose function with JavaScript by dev001hajipro (@dev001hajipro) on CodePen.0

 

JavaScriptで線がなめらかに動くスクリーンセーバー

JavaScriptで線がなめらかに動くスクリーンセーバーのようなものを作ってみました。一見複雑そうに見える動きは、単純に三角関数を足しているだけです。

See the Pen Recreating Vintage Computer Art with JavaScript by dev001hajipro (@dev001hajipro) on CodePen.0

 

HTMLのCanvasでピクセルソート(Pixel sort)

Canvas要素に画像を貼り付けてピクセルを操作できます。JavaScriptには、型付き配列というものがあります。これを使うことで、RGBA単位の操作またはピクセル単位の操作をうまく切り替えることができます。

参考資料

https://developer.mozilla.org/ja/docs/Web/Guide/HTML/Canvas_tutorial/Pixel_manipulation_with_canvas

CanvasのImageData.data属性の、型付き配列Uint8ClampedArrayとその使い方のチュートリアルです。このチュートリアルやデモを見ると画像をCanvasに表示して、グレースケールにする方法などが分かります。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Typed_arrays

型付き配列の説明です。型付き配列にはちょっと名前とは違い、バッファーとビューという概念があるためこれが理解する必要があります。逆にこれを使わずに、Uint8ClampedArrayを使うと、ループ処理のステップアップする数の調整などが非常に面倒になります。

 

デモ

See the Pen Pixel sort by dev001hajipro (@dev001hajipro) on CodePen.0

ソースコード

解説

5行目のimg.crossOrigin=”Anonymous”;は外部サイトの画像ファイルをCanvasに読み込むとセキュリティーエラーが発生するので、記述しています。

画像はWikipediaの320×320の画像で、Canvasのサイズを640×320にして、左側に修正していない画像を貼り付けて、右側にピクセルソートした結果を表示しています。

ctx.drawImage(img, 0, 0)が、オリジナルの画像をCanvasに描画している部分です。これはCanvasの入門情報を調べるとすぐに分かります。

var imageData = ctx.getImageData(0, 0, 320, 320);でCanvasに描画したピクセルデータが入ったImageDataオブジェクトを取得します。(ImageData -MDN) ImageData.dataプロパティーには、Uint3ClampedArray型のピクセルデータが入っています。何か難しい型に感じますが、単純に、RGBAのデータが並んでいるだけです。

単純にfor文で、ステップをi += 4にして、ループすることで、RGBAを操作することも可能です。

 

初期設定では、imageData.dataは、Uint8ClampedArray型で、ループなどをする場合は、ステップを4にする必要があります。ピクセルの移動のようにピクセル単位で操作したい場合は、forループなどのステップが1の場合の方が都合がよいです。そのような場合は、imageData.data.bufferから、Uint32Array型を用意して操作します。

ピクセル単位のソート処理

ピクセル単位に操作できるようになったので、Arrays.sortでソート処理を行います。引数p1は1ピクセルを表し、Uint32型なので符号なしの32ビットです。つまり以下のように、ABGRの順で1ピクセルを表します。

ビット演算

ビット演算は、RGBのr,g,bを各8bitとして取り出したいので、以下の手順で行います。

  1. シフト演算で、8bit単位で下位にずらす。
  2. 0xFF=11111111と論理積(AND)でマスクをする。

ビット演算の経験がなくちょっとわかりづらい場合は、ピクセルソートはひとまず置いておいて、ビット演算のみを勉強してみるとすんなり理解できると思います。

ビット演算で、r,g,bを取得できたので、とりあえずの明度としてr+g+b/3で値を用意して、比較しています。

あとは、putImageDataで、右側に書き込むだけです。

 

まとめ

最初は、Processingでピクセルソートをする動画を見たので試しました。Processingでのピクセル操作は分かりやすかったのですが、バブルソートで非常に遅く、原始的にRGBAを操作するのではなく、colorオブジェクトのように少しラップされたAPIのため、逆に分かりづらかったです。

そのためp5.jsなどがありますが、素のJavaScriptでピクセルソートを試してみました。Uint32Arrayと型付き配列を理解出来たら、あとは配列を操作するだけなので手間はありますが、非常に理解しやすかったです。

 

 

p5.jsでワードカウント

p5.jsで特定サイトの単語を数えるプログラムを書いてみました。HTMLを取得したら、doucment.textContentで、タグ内に書かれた文字列をすべて抽出します。次に、空白や改行などの記号を区切りとして単語に分割し、それを連想配列(Map)に格納します。

単語を抽出して連想配列にする場合は、関数型プログラミングの方法で実装するとすっきりするようです。