GTK+ で落書き 9(Ruby)

自作の Gem 'oekaki' で落書きしてみました。蚊取り線香? 何だか目が回ります。
 

 
コードは以下。何も考えずにテキトーにいきあたりばったりでコーディングしました。

require 'oekaki'

R = 7
Width, Height = 500, 500

Oekaki.app width: Width, height: Height do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, Width, Height)
  end
  
  p = Vector[0, 0]
  np = p.dup
  deg = 90
  r = 0
  step = 1.5
  
  b_line = lambda do |p1, p2|
    l = (p2 - p1).r
    pt = p1.dup
    0.upto(l) do
      color(0, 65535, 0)
      arc(true, Width / 2 + pt[0] - R, Height / 2 - pt[1] - R,
          R * 2, R * 2, 0, 64 * 360)
      pt += (p2 - p1) / l
    end
  end
  
  id = timer(50) do
    b_line.call(p, np)
    
    p = np
    θ = PI * deg / 180
    np = Vector[cos(θ), sin(θ)] * r
    r += step
    step_d = 20 - r / 35
    deg -= step_d
    Gtk.timeout_remove(id) if r > 220
    true
  end
end

関数 b_line は点 p1 から p2 へ太い線を引きます(円を動かしてやっています)。
お絵かきするのに標準添付ライブラリの Vector クラスや(ここでは使っていませんが)Matrix クラスは役立ちます。計算がだいぶ楽になりますよ。
 
Gen 'oekaki' については以下。
oekaki | RubyGems.org | your community gem host
GTK+でお絵かきしてみた(Ruby) - Camera Obscura

Haskell の Linux Mint(Ubuntu)へのインストール

Haskell の処理系は GHC(The Glasgow Haskell Compiler)が有名です。これを Linux にインストールしてみます。最新版はここからダウンロードしてインストールしますが、面倒なのでパッケージ・マネージャでインストールしました。
 

$ sudo apt-get install haskell-platform

だけでインストールできるので、とても簡単です。REPL(対話型実行環境)は

$ ghci
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Prelude> 2 + 15
17
Prelude> :q
Leaving GHCi.
$

という感じです。このとおり、パッケージの最新バージョンは 7.10.3 でした。このバージョンで問題はたぶんないと思います。ちなみに現在の最新版は 8.0.2 です。

Linux Mint 18.1 で確認しました。

Hello, World!

おなじみの「Hello, World!」をやってみます。

hello.hs

main = putStrLn "Hello, World!"

 
インタプリタで実行。

$ runghc hello.hs
Hello, World!

 
コンパイルして実行。

$ ghc -o hello hello.hs
[1 of 1] Compiling Main             ( hello.hs, hello.o )
Linking hello ...
$ ls
hello  hello.hi  hello.hs  hello.o
$ ./hello
Hello, World!

 
OK ですね!

ドラゴン曲線を描く(Ruby)

自己相似図形であるドラゴン曲線を Ruby で描いてみました。
 
3次。

5次。

10次。これだと確かにドラゴンみたいですね。

 
描画には自作の Gem 'oekaki' を使っています。 

require 'oekaki'

Width, Height = 600, 400

class Point < Struct.new(:x, :y)
end

Oekaki.app width: Width, height: Height, title: "Dragon curve" do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, Width, Height)
    
    drawing = proc do |a, b, depth|
      x = b.x - a.x
      y = a.y - b.y
      
      c = Point.new
      c.x = a.x + (x + y) / 2
      c.y = b.y + (x + y) / 2
      
      if depth.zero?
        color(0, 65535, 0)
        line(a.x, a.y, c.x, c.y)
        line(b.x, b.y, c.x, c.y)
      else
        drawing[a, c, depth - 1]
        drawing[b, c, depth - 1]
      end
      true
    end
    
    a, b = Point.new, Point.new
    a.x, a.y = 150.0, 150.0 
    b.x, b.y = Width - 150.0, 150.0
    
    drawing[a, b, 5]
  end
end

 
Gem 'oekaki' については以下。
oekaki | RubyGems.org | your community gem host
GTK+でお絵かきしてみた(Ruby) - Camera Obscura

マンデルブロ集合を描いてみる(Ruby)


 
このサイトのそのままパクリです(ありがとうございます!)。やったのは Java から Ruby へ移植しただけ。
 

def mandelbrot_count(c)
  z = Complex(0)
  100.times do |i|
    z = z ** 2 + c
    return i if z.abs > 10
  end
  100
end

Diff = 0.001
io = open("mandelbrot_data.dat", "w+")

-2.step(1, Diff) do |r|
  -1.step(1, Diff) do |i|
    value = mandelbrot_count(Complex(r, i))
    next if value.zero?
    io.puts "#{r}\t#{i}\t#{value}"
  end
  io.print "\n"
end

io.close

自分の環境では 4分あまりかかりました。
 
 
gnuplot で描画します。これは上サイトそのまま。

set pm3d
set pm3d map
set palette defined(0"#000099",1"#ffffff",2"black")
set terminal png size 1024,768
set output 'mandelbrot-pm3d.png'
splot 'mandelbrot_data.dat' notitle

 



追記。こちらもどうぞ。(2019/7/28)
obelisk.hatenablog.com

コッホ曲線を描く(Python, Ruby)

自己相似図形であるコッホ曲線を PythonRuby で描いてみました。


Python では手軽にタートル・グラフィックスが使えるので、これを利用するのが簡単です。

 
3次のコッホ曲線を描きます。

from turtle import *

def draw(length, depth):
    if depth == 0:
        forward(length)
    else:
        draw(length / 3, depth - 1)
        left(60)
        draw(length / 3, depth - 1)
        right(120)
        draw(length / 3, depth - 1)
        left(60)
        draw(length / 3, depth - 1)

color('firebrick')
up()
setx(-250)
down()

draw(500, 3)
input()

 
 
Ruby では簡単なタートル・グラフィックスを実装して描くことにします(Turtle クラス)。描画は自作の Gem 'oekaki' で行っています。

 
4次のコッホ曲線を描きます。

require 'oekaki'

Width, Height = 600, 300

class Turtle
  def initialize(x, y, ob)
    @pen_po = Vector[x, y]
    @pen = ob
    @dir = Vector[1, 0]
  end
  
  def left(deg)
    θ = PI * deg / 180
    @dir = Matrix[[cos(θ), -sin(θ)], [sin(θ), cos(θ)]] * @dir
  end
  
  def right(deg)
    left(-deg)
  end
  
  def forward(length)
    next_po = @pen_po + @dir * length
    @pen.line(Width / 2 + next_po[0], Height / 2 - next_po[1],
       Width / 2 + @pen_po[0], Height / 2 - @pen_po[1])
    @pen_po = next_po
  end
end


Oekaki.app width: Width, height: Height, title: "Koch curve" do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, Width, Height)
    
    t = Turtle.new(-250, -50, self)
    
    drawing = proc do |length, depth|
      if depth.zero?
        t.forward(length)
      else
        drawing[length / 3, depth - 1]
        t.left(60)
        drawing[length / 3, depth - 1]
        t.right(120)
        drawing[length / 3, depth - 1]
        t.left(60)
        drawing[length / 3, depth - 1]
      end
    end
    
    color(0, 65535, 0)
    drawing[500.0, 4]
  end
end

Python でも Ruby でもやっていることはほぼ同じです。

Gem 'oekaki' については以下。
oekaki | RubyGems.org | your community gem host
GTK+でお絵かきしてみた(Ruby) - Camera Obscura
 
誰かえらい人、Ruby でタートル・グラフィックスを実装しないですかね。初心者が遊ぶのに手頃だと思うのだけれど。自分でやれるといいのだけれど、Python みたいにインタラクティブに描画させるようにすると自分のスキルではむずかしそう。
自分で実装してみた
 
 
※参考
GTK+でヒルベルト曲線(Ruby) - Camera Obscura
Python の Turtle でヒルベルト曲線 - Camera Obscura

Ruby でローレンツアトラクタを描画する

Ruby + gnuplotローレンツアトラクタを描いてみました。
 

 
全体的にここなどを参考にしました。微分方程式オイラー法(参考)で数値計算しています。

gnuplot での描画は numo/gnuplot という Gem を使っています。

require 'numo/gnuplot'

fx = lambda {|x, y, z, r, p, b| -p * x + p * y}
fy = lambda {|x, y, z, r, p, b| -x * z + r * x - y}
fz = lambda {|x, y, z, r, p, b|  x * y - b * z}

dt = 1e-3
x, y, z = 1, 1, 1
p, r, b = 10, 28, 8 / 3.0

ax, ay, az = [], [], []

100000.times do
  x += dt * fx[x, y, z, r, p, b]
  y += dt * fy[x, y, z, r, p, b]
  z += dt * fz[x, y, z, r, p, b]
  ax << x
  ay << y
  az << z
end

Numo.gnuplot do
  unset :key
  splot ax, ay, az, w: :dots
end
gets    #終了待ち

1Ωの抵抗10個で黄金比の値に近づける(Ruby)

問題:

1Ω の抵抗 10個を使い、合成抵抗が黄金比 1.6180339887..Ωにもっとも近づく場合の値を、少数第10位まで求めよ。

 
aΩ と bΩ の抵抗をつなげる場合、直列つなぎにすれば合成抵抗はたんに a + b Ω になりますが、並列つなぎの場合はそれらの逆数の和の逆数、つまり
  
になるのが重要なところです。抵抗10個できわめて複雑な組み合わせをつくることができます。

Ruby で求めてみました。

require 'set'

def product(a, b)
  @ar[a].each do |i|
    @ar[b].each do |j|
      @ar[a + b] << i + j
      @ar[a + b] << (i * j) / (i + j)
    end
  end
end


@ar = Array.new(11) {Set.new}
@ar[1] << Rational(1, 1)
for i in 2..10
  for j in 1..(i / 2)
    product(j, i - j)
  end
end

ans = 10
@ar[10].each do |x|
  ans = x if (x - 1.6180339887).abs < (ans - 1.6180339887).abs
end
puts "%.10f" % ans.to_f
puts ans

答えは 1.6181818182 となります。分数だと 89/55 ですね。
ちなみに、模範解答よりもずっとシンプルなコードだと思います。

さて、これがどのような回路なのかですが、それも求めるとなるとさらに手を入れないといけないですね。だいぶ複雑になりそうです。