任意の階層だけ繰り返しをネストする多重 map 的メソッド(Ruby)

Array#nest_loop で、Integer#times の多重ネスト版です。配列にループ回数を入れて呼び出します。わかり切った多重ループを書くのが面倒なときに役立ちます。ブロックが与えられなければ Enumertor を返します。
 

[4, 2, 3].nest_loop do |i, j, k|
  print "#{[i, j, k]} "
end
#=>
[0, 0, 0] [0, 0, 1] [0, 0, 2]
[0, 1, 0] [0, 1, 1] [0, 1, 2]
[1, 0, 0] [1, 0, 1] [1, 0, 2]
[1, 1, 0] [1, 1, 1] [1, 1, 2]
[2, 0, 0] [2, 0, 1] [2, 0, 2]
[2, 1, 0] [2, 1, 1] [2, 1, 2]
[3, 0, 0] [3, 0, 1] [3, 0, 2]
[3, 1, 0] [3, 1, 1] [3, 1, 2]

 
for in 文を使って実装しているので、self の配列の中には範囲演算子や配列、ハッシュなどを使うことができます。また、ブロックのそれぞれの返り値が配列に入って返ります。なので、多重ループ版の map のように使えます。

p [2..6, 2, ["a", "b"]].nest_loop(&:itself)
#=>[[2, 0, "a"], [2, 0, "b"], [2, 1, "a"], [2, 1, "b"], [3, 0, "a"], [3, 0, "b"],
#   [3, 1, "a"], [3, 1, "b"], [4, 0, "a"], [4, 0, "b"], [4, 1, "a"], [4, 1, "b"],
#   [5, 0, "a"], [5, 0, "b"], [5, 1, "a"], [5, 1, "b"], [6, 0, "a"], [6, 0, "b"],
#   [6, 1, "a"], [6, 1, "b"]]

a = [:a, :b, :c]
p [a, a].nest_loop {|i, j| (j == :b) ? [i, "b"] : [i, j]}
#=>[[:a, :a], [:a, "b"], [:a, :c], [:b, :a], [:b, "b"],
#   [:b, :c], [:c, :a], [:c, "b"], [:c, :c]]



本体のコードです。(※注:2018/2/7 に修正しました。)
nest_loop.rb

class Array
  def nest_loop
    check = lambda do |obj|
      return 0...obj if obj.class.ancestors.include?(Integer)
      obj
    end
    
    e = Enumerator.new do |y|
      ns = lambda do |ax, args|
        a, ax = ax.first, ax.drop(1)
        for i in check.call(a)
          nxt = args + [i]
          if ax.empty?
            y << nxt
          else
            ns.call(ax, nxt)
          end
        end
      end
      ns.call(self, [])
    end
    block_given? ? e.map {|i| yield(i)} : e
  end
end

 

Gem 化

自家製の utility Gem 'kaki-utils' に同梱しました。
kaki-utils | RubyGems.org | your community gem host
インストールは $ gem install kaki-utils で。使い方は

require 'kaki/utils/nest_loop'

a = [1, 2, 3]
p [a, a].nest_loop {|i, j| i * j}    #=>[1, 2, 3, 2, 4, 6, 3, 6, 9]

という感じ。(2018/2/6)

GTK+で落書き 4(Ruby)

引き続き Gem 'oekaki' で落書きです。
oekaki | RubyGems.org | your community gem host
GTK+でお絵かきしてみた(Ruby) - Camera Obscura



Ruby コード。

require 'oekaki'
include Math

L = 300; O = L / 2
R = 140
step = 20

i = 0

Oekaki.app width: L, height: L do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, L, L)
    color(0x87 * 256, 0xce * 256, 0xeb * 256)    #skyblue
    arc(false, O - R, O - R, R * 2, R * 2, 0, 64 * 360)
  end
  
  id = timer(500) do
    ar = []
    θ = i * step * PI / 180
    x = R * cos(θ)
    y = R * sin(θ)
    ar << [O + x, O - y]
    3.times do
      x, y = -y, x
      ar << [O + x, O - y]
    end
    color(0x22 * 256, 0x8b * 256, 0x22 * 256)    #forestgreen
    polygon(false, ar)
    i += 1
    Gtk.timeout_remove(id) if i * step > 180
    true
  end
end

GTK+ でぽちぽち遊び(Ruby)

キャンバス上でマウスクリックして下さい。ぽちぽち円が描かれます。


右クリックで終了ボタンが出ます。


Ruby コード。

require 'oekaki'

L = 500; R = 25

Oekaki.app width: L, height: L do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, L, L)
  end
  
  quit_window = proc do
    make_window do |w|
      w.title = ""
      b = button do
        set_size_request(120, 40)
        add(Gtk::Label.new.set_markup('<span size="x-large">Quit!</span>'))
        signal_connect("clicked") {Gtk.main_quit}
      end
      add(b)
    end
  end

  mouse_button do |w, e|
    quit_window.call if e.button != 1
    color(rand(65536), rand(65536), rand(65536))
    arc(true, e.x - R, e.y - R, R * 2, R * 2, 0, 64 * 360) 
  end
end

 
Gem 'oekaki'(かつての 'mygtk')については
GTK+でお絵かきしてみた(Ruby) - Camera Obscura
メソッド Event#mouse_button, Event#make_window, Gtk::Window#button を加えました。
oekaki | RubyGems.org | your community gem host

複素フィボナッチ数列と GTK+ お絵かき

GTK+でお絵かきしてみた(Ruby) - Camera Obscura
これまで mygtk.rb と言っていた GTK+ お絵かきモジュールを、Gem 'oekaki' として RubyGems.org に登録いたしました。よろしかったら使ってやって下さい。
oekaki | RubyGems.org | your community gem host
その簡単な記録が
最小限度の Ruby Gem 作成と公開 - Marginalia
であります。


それとちょっと関係してといいますか、いつも拝読しているブログ「完全無欠で荒唐無稽な夢」の記事に、複素フィボナッチ数列というおもしろそうな題材がありましたので、お絵かきしてみました。数列を複素平面にプロットしただけであります。ただし、ものすごい勢いで原点から遠ざかったりもするので、原点からの距離は対数をとってあります。
複素フィボナッチ数列の件 - 完全無欠で荒唐無稽な夢

複素フィボナッチ数列とは,
  
というものですね。

まず、
  
の場合。

わかりにくいけれど、螺旋ですね。

上ブログ記事にあった、
  
の場合。

あんまり変わらないですかね。


Ruby のコード。

require 'oekaki'

L = 400
a = Complex(1, -1)
b = Complex(1,  1)

Oekaki.app width: L, height: L do
  draw do
    color(0, 0, 0)
    rectangle(true, 0, 0, L, L)
  end
  
  plot = lambda do |a|
    x1 = a.real
    y1 = a.imaginary
    r = Math.sqrt(x1 ** 2 + y1 ** 2)
    l = Math.log(r) * 2.5
    x = L / 2 + 1 + x1 * l / r
    y = L / 2 + 1 - y1 * l / r
    color(0, 65535, 0)
    arc(false, x, y, 3, 3, 0, 64 * 360) rescue return
  end  
  
  timer(20) do
    plot.call(a)
    a, b = b, b + Complex::I * a
  end
  
  key_in do |w, e|
    Gtk.main_quit if e.keyval == Gdk::Keyval::GDK_Return
  end
end

リターンキーで画面が閉じます。

Ruby Gem できた

野良 Gem の作り方(Ruby) - Camera Obscura
以前「野良 Gem」(「野良」なのは、僕が RubyGems.org に登録していないからです)を作ったのですが、いいかげんなやり方だったので、書き直してみます。

gem 'mygtk' を作ってみます。git が必要なので、なければインストールして下さい。
GitHub のアカウントに mygtk というリポジトリを作っておきます。
また、以下 Bundler を使うので、インストールしておいて下さい。


好きなディレクトリで

$ bundle gem mygtk

を実行します。すると mygtk フォルダが出来、色いろ他のファイルも作成されます。

$ cd mygtk

でフォルダの中に入ります。この中にある、mygtk.gemspec というファイルの中身を変更します。具体的には上のリンク先を見て下さい。spec.summary と spec.description は必ず中身を記述しなくてはなりません。また、依存する Gem があれば spec.add_dependency も記述します(標準添付ライブラリについては必要ありません)。

lib というディレクトリに入って、中の mygtk.rb を書きます(先頭に require "mygtk/version" が必要です)。これが require される Gem の本体になります。

git のインデックス(ステージ領域)に追加し、コミットします。

$ git add -A
$ git commit -m 'first commit'

Gem を作ります。

$ rake install

これで Gem が出来ているので、irb で require 'mygtk' などしてみて確認します。

リモートリポジトリ(この場合は GitHub)にファイルを上げます。

$ git remote add origin git@github.com:obelisk68/mygtk.git
$ git push -u origin master

リリースします。RubyGems.org に登録していれば、これで Gem が公開されます。登録していない場合はここでフリーズするので、しばらくして [Ctrl]+[C] で中断します。

$ rake release

これで GitHub に(野良)Gem が置かれました。終了です。


これで RubyGem に上げていれば、あとはふつうに Gem として使ってください。
「野良」の場合は、Bundler でインストールできます。Gemfile に

gem 'mygtk', github: 'obelisk68/mygtk'

と記述して、

$ bundle install

でインストールできます。使い方は以下。
GTK+でお絵かきしてみた(Ruby) - Camera Obscura


※参考
bundle gemは何をしてくれるのか? - ザリガニが見ていた...。
サルでもわかるGit入門 〜バージョン管理を使いこなそう〜 | どこでもプロジェクト管理バックログ

GitHub に SSH 接続

Linux Mintクリーンインストールし直したので、GitHub との SSH 接続をやり直す必要に迫られました。以下メモ。


公開鍵の作成。

$ ssh-keygen -t rsa

認証用のパスワードを二回入力する。

次に GitHub にログインして、SSH Key の登録をする。
[Settings]→[SSH and GPG keys]→[New SSH Key]
とすると入力画面になるので、[Title] のところには適当なタイトルを入れる。[Key] のところには、PC の ~/.ssh/id_rsa.pub の内容をコピペする。そして [Add SSH Key] で登録終了。

で、

$ ssh -T git@github.com

として認証されればおしまい。

あと、色いろやっていると

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.

とか言われるかもしれないので、言われたらおとなしく言われたとおりにする。登録してあるメールアドレスとアカウント名を "" の中に書いて実行してやる。


ああ、疲れた。

Linux Mint 18(Ubuntu)で Irfan View を使う


Windows 用のフリーの画像ビューアーである「Irfan View」は、動作が軽快で使っている人も多いと思います。残念ながら Linux 版はないのですが、「Wine」を使って多少の工夫で Linux でも走らせることができます。Linux Mint 18 で確認しました。


まず、Linux に「Wine」をインストールして下さい。Linux Mint なら「ソフトウェアの管理」から入れられます。

次に、例えばここから、Irfan View 本体(32bit 版)と日本語モジュールをダウンロードします(どこからでもかまいません)。自分の落としたのは、本体が v.4.44、日本語モジュールが v.4.40.01 でした。以下、バージョンは適宜読み替えて下さい。


Irfan View 本体のファイル名は「iview444_setup.exe」などとなっています。これを Wine の cドライブの「c:/ windows/system32」へ移動させます。そして端末で

$ wine iview444_setup.exe

を実行して下さい。たぶん

err:module:import_dll Library MFC42.DLL (which is needed by L"G:\\home\\tomoki\\iview444_setup.exe") not found
err:module:LdrInitializeThunk Main exe initialization for L"G:\\home\\tomoki\\iview444_setup.exe" failed, status c0000135

というエラーが出ると思います。ライブラリ・ファイルが足りません。そのときは端末で

$ winetricks -q mfc42

を実行して下さい(winetricks が入っていなければ、$ sudo apt install winetricks でインストールする)。MFC42.DLL がインストールされればOKです。そうしたら、もう一度 $ wine iview444_setup.exe を実行してみて下さい。セットアップ・プログラムが立ち上がればOKです。


セットアップ・プログラムの設定は Windows の場合と同じです。これが終了すれば Irfan View が使えます。Wine メニューから「Irfan View 4.44」を選択・実行して下さい。


最後に日本語化します。ダウンロードした日本語モジュール irfanview_lang_japanese.exe を右クリックし、「Wine Windows プログラムローダー」を選択して実行してみて下さい。これはこれだけでOKな筈です。あとはふつうに Wine メニューから「Irfan View 4.44」を立ち上げ、[Options]メニューから[Change Language]項目を選んで設定ダイアログの“Language”画面を表示、“JAPANESE.DLL”を選択すればOKです。


これで軽快な画像ビューア「Irfan View」が Linux でも使えます。
なお、元のファイル「iview444_setup.exe」「irfanview_lang_japanese.exe」は削除してかまいません。


※参考
Use Irfanview in Linux with Wine - Technicus
[SOLVED] Irfanview in Wine