Turtle Graphics on Ruby/SDL

2010年2月 1日 (月)

既約分数クイズ、ファレイ数列、フォードの円

 こちらのブログ「既約分数クイズ」の存在を知りました。

 ちょっと面白そうだったので、Haskell でコードを書いてみました。答えは (分子, 分母) の組がリストの形で出てきます。

irreducibleFraction :: Int -> [(Int, Int)] irreducibleFraction n = [(p, q) | q <- [1 .. n], p <- [0 .. q], gcd p q == 1]
*Main> irreducibleFraction 4 [(0,1),(1,1),(1,2),(1,3),(2,3),(1,4),(3,4)]
 Haskell では条件を書くだけで、何の工夫もせずに答えが出てしまいました。

 「他の解法はないものか?」と調べていたら、既約分数に関連して「ファレイ数列」というものがあることが分かりました。これは既約分数が大きさの順に並んでいるものです。
 そこで、先ほどの関数を使って「ファレイ数列」を作ってみることにしました。ついでにより分数らしく見えるようにしてみました。

import Ratio import Data.List irreducibleFraction :: Int -> [(Int, Int)] irreducibleFraction n = [(p, q) | q <- [1 .. n], p <- [0 .. q], gcd p q == 1] farey :: Int -> [(Int, Int)] farey n = sortBy comp (irreducibleFraction n) where comp (p1, q1) (p2, q2) = compare (p1 % q1) (p2 % q2) fareyToStr :: [(Int, Int)] -> String fareyToStr ns = init $ concat $ map toStr ns where toStr (a, b) = show a ++ "/" ++ show b ++ " "
*Main> fareyToStr $ farey 4 "0/1 1/4 1/3 1/2 2/3 3/4 1/1"
 さらに調べると、「ファレイ数列」には「中関数」を使って求める方法があるようなので、自分でも考えて見ました。
farey2 :: Int -> [(Int, Int)] farey2 n = farey' [(0, 1), (1, 1)] where farey' ((x1, y1) : xs@((x2, y2) : _)) | y1 + y2 > n = (x1, y1) : farey' xs | otherwise = farey' ((x1, y1) : (x1 + x2, y1 + y2) : xs) farey' xs = xs
*Main> fareyToStr $ farey2 4 "0/1 1/4 1/3 1/2 2/3 3/4 1/1"

 

 ところで Wikipedia の「ファレイ数列」の項には「フォードの円」という図が載っています。
 「これって、自作の "Turtle Graphics on Ruby/SDL" で描けるかな?」ということでコードを書いてみました。

# -*- coding: utf-8 -*- require 'turtle_graphics' # # == ファレイ数列 # def farey(n) q_arr = (1 .. n).to_a p_arr = Array.new f_arr = Array.new farey = q_arr.each do |q| p_arr = (0 .. q).to_a f_arr.push(p_arr.map {|p| [p, q]}) end f_arr = f_arr.flatten(1).select{|p, q| p.gcd(q) == 1} return f_arr.sort_by{|p, q| p / q.to_f} return end # # == フォードの円を描く # class Screen def ford_circle(p, q, c) q = q.to_f r = 1 / (2 * q * q) draw_circle(p / q, r, r, c).update # draw_circle(p / q, 1 - r, r, c).update end end sc = Screen.create(600, 600) sc.set_range(0, 1, 0, 1) # 描画範囲 (x_min, x_max, y_min, y_max) farey(10).each do |p, q| sc.ford_circle(p, q, White) end sc.main_loop

Screenshotturtle_graphics_on_rubysd

 Wikipedia には F5 の図が載っていますが、今回のコードでは F10 の図を描いてみました。
 当然、コードを書き換えれば F50 だろうが F100 だろうが表示してくれます(相当時間がかかると思われますが……)
 また、描画範囲を書き換えて拡大表示させれば、小さい円もそれぞれしっかり他の円に接しているのがわかります。
 ただし、あまり大きく拡大表示すると、0/1 の円と 1/1 の円の表示が乱れるようです。これは "turtle_graphics.rb" の "Screen#draw_circle" 内で使用している、"draw_aa_circle" というメソッドの問題のようです。この部分を "draw_circle" に書き換えれば、どんなに拡大しても表示は乱れないと思われます。

2009年4月 3日 (金)

数学ガール --- ωのワルツ

Omega1_5


遅ればせながら、昨日から『数学ガール』を読んでいます。

何となく買いそびれていたのですが、昨日、意を決して買ってみました。

いや〜おもしろい。しかも読みやすい。


ところでこの本の中に「ωのワルツ」という章がありますよね。

初項 C0 = 0, 公比 ω = ( -1 + √3 i ) / 2

の等比数列が、1, ω, ω² を繰り返すというやつです。

これが複素平面上で正三角形を形作るという話ですが、本当にそうなのか確かめたくて、 自作の「Turtle Graphics on Ruby/SDL」を使った、下記のようなスクリプトを作ってみました。

# # ωのワルツ # # from 『数学ガール』 # require 'turtle_graphics' require 'complex' class Turtle def move_to(x, y) dx = x.to_f - @x dy = y.to_f - @y case when (dx < 0) @angle = atan(dy / dx) / TO_RADIAN - 180 when (dx == 0) case when (dy < 0) @angle = 270 when (dy > 0) @angle = 90 end when (dx > 0) @angle = atan(dy / dx) / TO_RADIAN end len = sqrt(dx * dx + dy * dy) forward(len) end self end s = Screen.create s.set_zoom(160).grid_on s.set_speed(4) s.draw_circle(0, 0, 1, Blue) t = Turtle.new(1, 0) # Turtle.verbose_on t.set_color(Yellow) omega = Complex.new(-0.5, 0.5 * sqrt(3)) c = 1 loop do c = c * omega x = c.real y = c.image t.move_to(x, y) end s.main_loop

これは、横軸を実数軸、縦軸を虚数軸に見立てた複素平面で、ωの作る等比数列の示す点を 亀がたどって行くものです。青い円は複素平面の単位円です。

単に正三角形を描いているように見えますが、内部では虚数の計算をしながら、実際にωつくる 等比数列の項を順々に求めています。

こうして実際に亀が動く軌跡を見てみると、ちょっとした感動があります。


ちなみに

omega = Complex.new(0, 1)

とすると、『数学ガール』のp44の正方形上の移動を再現できます。

2009年1月 8日 (木)

Turtle Graphics on Ruby/SDL ver.2.0

Sample_8

 

約一年半前にリリースした「Turtle Graphics on Ruby/SDL」をバージョンアップしました。

前回リリースした後も、自分で使いやすいように手を加えていった結果、メソッドの挙動やメソッド名がかなり変わってしまいました。以前のバージョンとは互換性はありません(以前のバージョンを使い込んでいた人がいたらごめんなさい)。

今回の変更で見てもらいたいのは、Screen#main_loop メソッドと Graph クラスです。

Screen#main_loop 実行中にマウスで拡大させたい領域を選択できるようになりました。 loop や while などのループ内に Screen#main_loop を含む処理を書いておくと、画面の一部をどんどん拡大して表示していくことができます。 (sample/Turtle_Graphics/koch_curve.rb 参照)

Graph クラスでは、通常の y = f(x) といった形の関数の他に、媒介変数を用いた、 y = f(t), x = g(t) といった形の関数も表示できます。

タートル・グラフィックスに関心のある方、手軽に関数のグラフを可視化してみたい方は、ぜひ一度、このライブラリで遊んでみてください。

「Turtle_Graphics_2.0.zip」をダウンロード

2007年5月17日 (木)

とりあえず アップ

「Turtle_Graphics-1.01.zip」をダウンロード

Tg01 Tg02

以前から趣味でチョコチョコとつくっていた、Ruby/SDL上で動くタートルグラフィック用のライブラリが、実用に耐えられるレベルになったようなので、とりあえずアップしてみました。


ちなみに

  • Rubyとは……オープンソースの動的なプログラミング言語で、 シンプルさと高い生産性を備えています。 エレガントな文法を持ち、自然に読み書きができます。(Rubyの公式ホームページ<http://www.ruby-lang.org/ja/>より引用)
  • Ruby/SDLとは……SDLとは、そのドキュメントによると、「マルチプラットフォームなマルチメディアライブラリ」であり、 Rubyとは、まつもと氏によるオブジェクト指向スクリプト言語です。そして、Ruby/SDLはRubyからSDLを利用できるようにするためのライブラリです。つまりはRubyでゲームなどを作るためのライブラリと言えます。(Ruby/SDLのホームページ<http://www.kmc.gr.jp/~ohai/rubysdl.html>より引用)

"Ruby"という言葉にピン!ときた方は試しにダウンロードして遊んでみてください。

訂正:

初めにアップロードした "Turtle_Graphics-1.0.zip" に "setup.rb" が入っていないことが判明しました。

"setup.rb" を同梱したものを改めて "Turtle_Graphics-1.01.zip" としてアップロードし直しました。

既に、ダウンロードされた方には大変ご迷惑をおかけしたと思います。すみませんでした。

追記:

バージョンアップ版を出しました。詳しくは2009年1月8日の記事を見てください。

2016年7月
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
フォト

最近のトラックバック

無料ブログはココログ