黄金の花を愛でる - 素数夜曲より -


 整数論の独学者用教科書「素数夜曲」がリニューアルされたので、コンテンツで遊んでみました。この本で取り上げられているプログラミング言語はSchemeなので、それをまぁF#に移植しただけとも言いますが....

 詳しいことは本を買って読んでください。整数論の玉手箱をひっくり返したような本で、いわば「宝の山」です。

ソース

//  Himawari   K. Katayama with Sosuu Yakyoku
 
open System
open System.Drawing
open System.Windows.Forms

let a = 1
let b = 13

let rational x y = Seq.unfold (fun n -> if n = 0 then None
                                                 else Some (n / y, (n % y) * 10)) x

let phi = (1. + sqrt(5.)) / 2.
let ang = (2. * Math.PI) / (1. + phi)
let size = 75.
let k x = (0.998 ** x) * 1.

let brushes = [| 
                 Brushes.Black;       Brushes.Brown;
                 Brushes.Red;         Brushes.Orange;
                 Brushes.Yellow;      Brushes.Green;
                 Brushes.Blue;        Brushes.Violet;
                 Brushes.Gray;        Brushes.LightGray;
              |]

let form = new Form(Text="Himawari", Width=640, Height=640)
form.Paint.Add(fun e -> 
  rational a b |> 
  Seq.take 2000 |>
  Seq.iteri (fun i ra ->
    let sheeta = (float i) * ang
    let x = Math.Cos sheeta
    let y = Math.Sin sheeta
    let r = k (float i)
    let rr = size * r
    let viewp = 380.0 - rr / 2.0
    e.Graphics.FillEllipse(
      brushes.[ra], 
      float32 (x * r * 320.0 + viewp),
      float32 (y * r * 320.0 + viewp),
      float32 rr,
      float32 rr)
  )
)

form.Show()

ざっくりとした解説

 最初のa,bは定数で、後程解説します。

 rationalは、xをyで割った時の答えを、求められる限り永遠に出力するシーケンスです。これの出力にしたがって色を付けます。

 それに続くletは定数ですが、このプログラムのキモになる黄金比を計算しています。

 brushesは、0~9までの数に対応する色を配列として保持します。

 form以下はウィンドウを開き、描画をする部分です。

実行結果

 実行はソースを丸ごとfsiのコンソールに転送すればOKです。


 また、ソース先頭のaとbの値を変更することで、a/bを無限小数として表した数列パターンで描画することができます。上のソースは、1/13つまり「0.0769230769230769...」という数列に従って色を付けたものになっています。
 ほかにも、
 1/11(a = 1, b = 11)

 22/7(a = 22, b = 7)

 3/19(a = 3, b = 19)

 1/21(a = 1, b = 21)

 1/57(a = 1, b = 57)

 また、チャンパーノウン定数というものがありまして、どういう数かというと、0.の次に自然数を順にダラダラ桁などお構いなしに書いていくことで得られる数(無理数でしかも超越数)です。
 0.12345678910111213141516171819202122232425262728293031....
 これを生成する関数も作ってみました。
let champernowne =
  Seq.initInfinite string |>
  Seq.concat |>
  Seq.map (fun c -> (int c) - (int '0'))
 上のソースの
  rational a b |> 
 を
  champernowne |> 
 とすることで、次のような、独特のパターンも得られます。

 などなど、文字通り切りがないほどいろいろなパターンを生成できます。
 簡単なので、ぜひ試してみてください。

(文責:片山 功士  2012/06/29)

今日: -
昨日: -
トータル: -
最終更新:2012年06月29日 20:32