しょんぼり技術メモ

まいにちがしょんぼり

gnuplotでグラフを表示しているときに使えるショートカットキー

自分用メモ。ウインドウでhを押せばヘルプが出るのでそれを読めば解決するけど。

キー 機能
1〜4 座標表示のフォーマットを変更(?)
5 定規(ruler)表示時の距離を表示するか
6 ショートカットキーのコマンド内容を表示するか
7 図全体のアス比を変更
q 閉じる
e リプロット
r 定規(ruler)を表示するか
u 右クリックズームの履歴をクリア
p 右クリックズームの履歴を戻る
a 各軸のスケールを自動で設定
g グリッドを表示するか
h ヘルプを表示
l 対数軸にするか
b 枠の設定
n 右クリックズームの履歴を進める
m マウスを有効にするか
上下左右 3D時の視点移動

p,u,nがマウスによる右クリックズームの機能に対応するものだ、とご指摘頂いたので修正しました

EmacsからYahoo翻訳を使う

国際会議の論文を書いていて、ある程度固まってきたので英訳する作業を始めたものの、いちいち書いてはYahoo翻訳にかけてチェック、書いてはチェックを繰り返すのは非常にめんどくさいので、なんとかならないかと思ってやってみた。

・できること
Emacsで範囲選択してコマンドを呼ぶと、その領域を翻訳した結果がミニバッファに出てくる

モノはこちら:use Yahoo! Translation via STDIN and utilize from Emacs for editing LaTeX · GitHub

Gist:

Emacsのshell-command-on-regionを使うと、範囲選択した部分のデータをコマンドの標準入力に渡すことができます。
region2trans.rbに"en2ja"や"ja2en"を渡すと、標準入力から読んだデータを日本語に/英語に翻訳したモノが出力されます。
これの組み合わせで実現しています。

論文はLaTeXで書いているので、いくつか前処理したい表記(\citeとかは無視して欲しい)ので、そのフィルタを噛ませてから呼んでます。latex_filter.rbがそれで、今のところものすごく手抜きです。。。

翻訳の使い方についてのガイドラインがはっきりしないので断言はできませんが、http://help.yahoo.co.jp/help/jp/honyaku/honyaku-18.htmlを見る限り、二次的に提供するようなサービスをしなければ大丈夫でしょう。たぶん。まあ個人的に使って下さい。

・Yahoo翻訳について
翻訳APIを叩く際、_crumbというパラメータがないと怒られるようです。この_crumbは、翻訳ページを開いた際のhiddenな要素から値を取得しているので、このスクリプトでも同じような動作を行わせています。これさえなければもっと短時間で書けたのに…

・免責事項
なにがどうなってもぼくはしらないよ。

・ライセンス
修正BSDライセンスでお願いします。好きにしてください。

ローソンWeb会員で、他のサービスではログインできるのにローチケのみログインできない場合には、メールアドレスを"+"が含まれていないものに変更すれば良い

タイトルで完結シリーズ。

某チケットの抽選予約に申し込むためにローチケ.comに会員登録したものの、ログインできないという問題に直面した。
Pontaを持っているのでローソンWeb会員として登録。パスワードに誤りがないことは、提携している他のサービス(HMVなど)で確認済みだが、なぜかローチケだけログインできない。

何度となくパスワードの変更を繰り返してもダメで、ためしにHMVにログインしてメールアドレスを"+"を含まないものに変更、その後同じパスワードでログインしようとしたら見事に通った。wtf。

というわけで、ローチケのログインにはバグがあるようです。登録時にはちゃんと通ったんですが、ローチケだけは会員種別か何かの関係で違うロジックを使っているんですかね。

MessagePack RPC for Rubyのタイムアウト系のエラーについてのメモ

忘れてたので自分用にまとめておく。

サーバ側:

require 'msgpack/rpc'

class MyServer
  def ping_sync
    "pong"
  end

  def ping_async
    as = MessagePack::RPC::AsyncResult.new
    # as.result("pong")
    as.result("pong at #{Time.now}")
    return as
  end

end

mysvr    = MyServer.new
mpserver = MessagePack::RPC::Server.new
mpserver.listen("127.0.0.1", 18888, mysvr)
mpserver.run

同期呼び出しのときのテスト。

require 'msgpack/rpc'

ret      = nil
mpclient = nil

begin
  mpclient = MessagePack::RPC::Client.new("127.0.0.1", 18888)
  mpclient.timeout = 1
rescue
  # この時点でサーバがListenしていなかった場合、
  # ここでTimeoutするように見える…が、実はそうでもない。ここではなにもraiseされてこない。
  puts "caught: #{$!.inspect}"
  exit 1
end

puts "--- call sync"
begin
  puts "calling mpclient.call(:ping_sync)"
  ret = mpclient.call(:ping_sync)
  puts "ret: #{ret}"
rescue
  # callしたときにサーバがListenしていないと、MessagePack::RPC::ConnectionTimeOut例外が上がる
  puts "caught: #{$!.inspect}"
  # -> caught: #<MessagePack::RPC::ConnectionTimeoutError: connection timed out>
  exit 1
end

非同期呼び出しのときのテスト。

require 'msgpack/rpc'

ret      = nil
mpclient = nil

begin
  mpclient = MessagePack::RPC::Client.new("127.0.0.1", 18888)
  mpclient.timeout = 10
rescue
  # この時点でサーバがListenしていなかった場合、
  # ここでTimeoutするように見える…が、実はそうでもない。ここではなにもraiseされてこない。
  puts "caught: #{$!.inspect}"
  exit 1
end

future = nil
begin
  puts "calling mpclient.call_async(:ping_async) at #{Time.now}"
  future = mpclient.call_async(:ping_async) # 返値はFutureクラス、この時点ではサーバ側では処理が行われない
  puts "future.class = #{future.class}"
rescue
  # call_asyncした時点でサーバがListenしていない場合でも、ここではなにもraiseされてこない。
  puts "caught: #{$!.inspect}"
end

puts "sleeping for 5 sec."
sleep 5

begin
  puts "-> calling Future.get"
  ret = future.get
  puts "ret = #{ret} / Time.now=#{Time.now}"
  puts "future.class = #{future.class}"
  puts "ret.class    = #{ret.class}"
rescue
  # ここで初めてping_asyncの処理が走る。サーバがListenしていない場合には例外が上がる
  puts "caught: #{$!.inspect}"
  # 最初からサーバがListenしていなかった場合:
  # -> caught: #<MessagePack::RPC::ConnectionTimeoutError: connection timed out>
  # 最初はサーバがListenしていたが、処理中に時間がかかりすぎてタイムアウトした場合:
  # -> caught: #<MessagePack::RPC::TimeoutError: request timed out>
  exit 1
end

asyncの実行結果:

calling mpclient.call_async(:ping_async) at 2011-11-08 16:49:00 +0900 # call_asyncを呼んだのは16:49:00
future.class = MessagePack::RPC::Future
sleeping for 5 sec.
-> calling Future.get
ret = pong at 2011-11-08 16:49:05 +0900 / Time.now=2011-11-08 16:49:05 +0900 # サーバ側でping_asyncが呼ばれたのは16:49:05
future.class = MessagePack::RPC::Future
ret.class    = String

要約:

  • Client.newした時点でサーバがListenしていなくても例外は上がらない
  • call, call_asyncした時点でサーバがListenしていないとMessagePack::RPC::ConnectionTimeoutErrorが上がる
  • call, call_asyncしてサーバが処理をしているとき、時間がかかりすぎてタイムアウトした場合にはMessagePack::RPC::TimeoutErrorが上がる
  • call_async(:remote_func, args) で呼び出したとしても、サーバ側ではまだremote_funcは呼び出されない。返値のfutureに対してgetを呼ぶと初めて実行が行われる

Rubyで配列に対して空かも知れない配列を追加する時は、事前にempty?でチェックした方が早いが、まとめて追加してから一気にflattenした方が圧倒的に早いが、そんなことするよりconcatした方が早い。

タイトルで完結シリーズ。(ご指摘頂いたArray#concatについて追記しました)

ある配列に対して、「空かもしれない配列」を追加していく処理が必要になった。

fruits1 = [:apple, :orange]
fruits2 = []
fruits3 = [:grape]

fruits_array = [fruits1, fruits2, fruits3]

こんな配列から、"[ :apple, :orange, :grape ]"こんな結果が欲しいときについて。普通はfruits_array.flattenで終わるけど。


配列に対して配列を"<<"で追加すると、配列には配列が格納される。(わかりにくい表現だ)

ruby-1.9.2-p0 > a1=Array.new
 => [] 
ruby-1.9.2-p0 > a2=[:apple, :orange]
 => [:apple, :orange] 
ruby-1.9.2-p0 > a1 << a2
 => [[:apple, :orange]] 
ruby-1.9.2-p0 > a3=[:grape]
 => [:grape] 
ruby-1.9.2-p0 > a1 << a3
 => [[:apple, :orange], [:grape]] 

それが嫌な場合には、"+="で追加すれば良い。

ruby-1.9.2-p0 > a1=Array.new
 => [] 
ruby-1.9.2-p0 > a2=[:apple, :orange]
 => [:apple, :orange] 
ruby-1.9.2-p0 > a1 += a2
 => [:apple, :orange] 
ruby-1.9.2-p0 > a3=[:grape]
 => [:grape] 
ruby-1.9.2-p0 > a1 += a3
 => [:apple, :orange, :grape] 

もし追加する対象に空配列"[]"があった場合、empty?で判断してから追加するのが良いのか、問答無用で+=を呼んでも大差ないのか、という疑問が浮かんだので、実際に試してみた。
10000個、ランダムに空配列or空じゃない配列を作成して、それをフラットな配列にする関数についてベンチマーク
ついでに、<<で追加して、最後にflattenでフラットな配列にする場合についても比較してみた。
さらに、concatで繋げていく場合についても比較してみた。(追記)


結果から:

$ ruby --version
ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux]
$ ruby ./arraytest.rb
                   user     system      total        real
Rehearsal --------------------------------------------------
without  check   0.210000   0.010000   0.220000 (  0.225342)
with     check   0.090000   0.010000   0.100000 (  0.104588)
flat w/  check   0.010000   0.000000   0.010000 (  0.003227)
flat w/o check   0.000000   0.000000   0.000000 (  0.003293)
concat each      0.000000   0.000000   0.000000 (  0.001726)
----------------------------------------- total: 0.330000sec

                     user     system      total        real
without  check   0.200000   0.030000   0.230000 (  0.218026)
with     check   0.100000   0.000000   0.100000 (  0.104849)
flat w/  check   0.000000   0.000000   0.000000 (  0.003143)
flat w/o check   0.010000   0.000000   0.010000 (  0.003293)
concat each      0.000000   0.000000   0.000000 (  0.001738)
okay.

concatがブッチギリに速い。flattenはその次に速い。empty?で比較する場合は比較なしで問答無用で+=する場合に比べて倍ぐらい速い。
flattenを使う場合、empty?で比較することの効果はあまり大きくないが、確かに差は生じる。でもconcatの方がはやーい。

結論:+=じゃなくてconcat使え。


以下ベンチマークコード。

require 'benchmark'

def with_check(source_array)
  ary = Array.new

  source_array.each do |s|
    if s.empty? == false
      ary += s
    end
  end

  return ary
end

def without_check(source_array)
  ary = Array.new

  source_array.each do |s|
    ary += s
  end

  return ary
end

def do_flat_with_check(source_array)
  ary = Array.new

  source_array.each do |s|
    if s.empty? == false
      ary << s
    end
  end

  return ary.flatten
end

def do_flat_with_check_dest(source_array)
  ary = Array.new

  source_array.each do |s|
    if s.empty? == false
      ary << s
    end
  end

  ary.flatten!
  return ary
end

def do_flat_without_check(source_array)
  ary = Array.new

  source_array.each do |s|
    ary << s
  end

  return ary.flatten
end

def do_concat_whole(source_array)
  ary = Array.new

  ary.concat(source_array)

  return ary
end

def do_concat_each(source_array)
  ary = Array.new

  source_array.each do |s|
    ary.concat(s)
  end

  return ary
end

ary_size = 10_000

# prepare
src_array = Array.new
ary_size.times do
  if (rand(2)==1)
    src_array << [1,2]
  else
    src_array << []
  end
end

puts "             " + Benchmark::CAPTION
ret1 = ret2 = ret3 = ret4 = ret5 = ret6 = nil
Benchmark.bmbm do |x|
  x.report("without  check") {
    ret1 = without_check(src_array)
  }
  x.report("with     check") {
    ret2 = with_check(src_array)
  }
  x.report("flat w/  check") {
    ret3 = do_flat_with_check(src_array)
  }
  x.report("flat w/o check") {
    ret4 = do_flat_without_check(src_array)
  }
  x.report("concat each  ") {
    ret5 = do_concat_each(src_array)
  }
  # x.report("concat whole   ") {
  #   ret6 = do_concat_whole(src_array)
  # } 全体にconcatしてもフラットな配列にはならない!
end

if (ret1 != nil) and (ret1 == ret2) and (ret2 == ret3) and (ret3 == ret4) and (ret4 == ret5) # and (ret5 == ret6)
  puts "okay."
end

MacでGX-DVI/U2AIを使ってDVI接続のモニタをUSB経由で利用する際にはDisplayLink社のページからβドライバをダウンロードすれば良い。回転させる場合にはDisplayRotationMenuを使うと良い。

タイトルで完結シリーズ。

MBP13"にDisplayPort経由で30インチモニタを繋ぎ、USB-DVI変換アダプタを使ってさらにもう一枚モニタを繋いでいるのですが、あっさり使えるようにはならないのでメモ。

ドライバはBUFFALOには置いてないので、http://displaylink.com/support/mac_downloads.phpからダウンロード。Lion対応。
これでモニタの増設はOK。ただし、ディスプレイを回転させようとすると、ディスプレイの設定画面に「回転」の項目がなくて困ってしまう。
そこで、Display Rotation Menu http://www.magesw.com/displayrotation/を入れて、このツールから回転させればOK。たぶん。