テストがないと何をしているのかわからんよね

id:epsilon_deltaさんの記事
10分でコーディングをやってみた - ボクは算数以外しか出来なかった
を読んでRubyで書いてみた。
zipでやってみます。


できてるっぽいけど、何をやってるのかがわかりにくいなー

require 'rspec'

class Cards

  def self.deal(num_players, deck)

    players = Array.new(num_players){ "" }

    players.zip(*deck.chars.each_slice(num_players).take(deck.size/num_players)).map(&:join)

  end

end

describe Cards do

  describe "#deal" do

    it "ex0" do
      Cards.deal(4, "123123123").should == ["12", "23", "31", "12"]
    end

    it "ex1" do
      Cards.deal(6, "012345012345012345").should == ["000", "111", "222", "333", "444", "555"]
    end

    it "ex2" do
      Cards.deal(4, "111122223333").should == ["123", "123", "123", "123"]
    end

    it "ex3" do
      Cards.deal(1, "012345012345012345").should == ["012345012345012345"]
    end

    it "ex4" do
      Cards.deal(6, "01234").should == ["", "", "", "", "", ""]
    end

    it "ex5" do
      Cards.deal(2, "").should == ["", ""]
    end

  end

end

BOM!BOMB!BON!(意味なし)

module function Kernel.#open

エンコーディングの指定

ext_enc(外部エンコーディング)が指定されている場合、読み込まれた文字列にはこのエンコーディングが指定され、出力する文字列はそのエンコーディングに変換されます。

ext_encが'-bom'で終わる場合、その入力に含まれるBOMはあらかじめ削られます。また、BOMがあった場合、入力された文字列にはそのBOMに対応するエンコーディングが設定されます。

int_encも指定されていた場合、入力された文字列をext_encでエンコーディングされた文字列とみなしてint_encへと変換し、その結果にint_encを設定して返します。 

引用:[http://doc.ruby-lang.org/ja/1.9.2/method/Kernel/m/open.html:title=module function Kernel.#open]

リファレンスでたまたま見つけてビックリした。
えぇ〜〜〜、わざわざBOM削ってたよorz


つーか、Encodingに-bomで終わるのなんてあたっけ?
ということでirbで確認

Encoding.list.map(&:to_s).grep(/bom/)
# => [] 

あれ??ないじゃんw
ないけど付ければいいってこと?

puts File.open("utf8.txt", "r:UTF-8-bom"){ |fp| fp.read(3).dump }
# => warning: Unsupported encoding UTF-8-bom ignored

だよねー
色々やってみたけど、わからず


念のためこっち(Index of Classes & Methods in Ruby 1.9.3 (Ruby 1.9.3) )で確認したら…
『If ext_enc starts with ‘BOM|’,〜 』ってなっている!!
ってことでコチラが正解

puts File.open("utf8.txt", "r:UTF-8"){ |fp| fp.read(6).dump }
# => "\xEF\xBB\xBF20\t"
puts File.open("utf8.txt", "r:BOM|UTF-8"){ |fp| fp.read(3).dump }
# => "20\t"
puts File.open("utf8n.txt", "r:BOM|UTF-8"){ |fp| fp.read(3).dump }
# => "20\t"

おー、イイ感じ!
無理矢理削るのがなんかイヤだったのでコレは嬉しいw


全然関係ないが、今日、3点足りなくて失敗した「1日で黄金聖闘士」計画の残念賞(銀)が届いていた。
自分にとっては残念賞だったし、全然期待していなかったんだけど、思ったより以上に良いモノだった
ので、やっぱり黄金が欲しくなった。

ASR便利!

artonさんの

WIN32OLEの高速化手法 - L'eclat des jours(2011-02-07)

Rubyizeのインプロセス/インスレッド化 - L'eclat des jours(2011-02-09)

記事を読んで、スクリプトを文字列で渡しても実行可能とあったのでやってみた。
<実行環境>
Windows 7 64bit
ASR (Ruby-1.9.2-p136 Microsoft Installter Package(2010-12-25))
Excel 2002


スクリプトは[script.rb]ファイルを文字列として読み込む。
[RubyModule.bas]モジュールをExcelにインポートして、execRubyをマクロ実行する。


[RubyModule.bas]

Attribute VB_Name = "RubyModule"

Sub execRuby()

    Dim ruby    As Object
    Dim script  As Object
    
    Set ruby = CreateObject("rubyize.object.1.9")
    Set script = ruby.erubyize(loadScript())
    
    MsgBox script.exec(ActiveWorkbook)

End Sub

Function loadScript() As String

    Dim fileSystem  As New Scripting.FileSystemObject
    Dim textStream  As Scripting.textStream
    Dim filepath    As String
    Dim code        As String

On Error GoTo Err

    'FileSystemObject生成
    Set fileSystem = New Scripting.FileSystemObject
    'ファイルパスを取得
    filepath = fileSystem.GetAbsolutePathName(ActiveWorkbook.Path & "\script.rb")
    'ファイルを開く
    Set textStream = fileSystem.OpenTextFile(filepath, ForReading, False, TristateUseDefault)
    'ファイルの内容を読み出し
    code = textStream.ReadAll
    
    'クローズ
    textStream.Close
    Set textStream = Nothing
    Set fileSystem = Nothing
    
    loadScript = code
    
    Exit Function

Err:
    'エラー
    Set textStream = Nothing
    Set fileSystem = Nothing
    MsgBox (Err.Description)
    
End Function



スクリプトは実行する.xlsファイルの名前と同じ名前のメソッドが実行するようにした。
[sample.xls]なら[script.rb]のsampleメソッドが呼び出される。
[ex01.xls]なら[script.rb]のex01メソッドが呼び出される。
[XXX.xls]とメソッドXXXがある[script.rb]は同じフォルダに置いておく。


[script.rb]

# coding: CP932

args = {
  sample: nil,
  ex01: [1..65536, 'A'..'IV'],
}

Script = Class.new do
  
  define_method :sample do |book, *params|
    start = Time.now
    sheet = book.worksheets(1)
    1.upto(10000) do |row|
      cells = sheet.Range(sheet.Cells(row, 1), sheet.Cells(row, 26))
      values = cells.Value
      26.times do |col|
        if row.even?
          values[0][col] = 3
        else
          values[0][col] = 'こんにちは'
        end
      end
      cells.Value = values
    end
    %{Elapsed time: #{Time.now - start} secs}
  end
    
  define_method :ex01 do |book, *params|
    start = Time.now
    rows, cols, * = [*params].flatten
    cols = alpha_to_num(cols)
    sheet = book.worksheets(1)
    sheet.Name = File.basename((book).Name, ".*")
    rows.each do |row|
      cells = sheet.Range(sheet.Cells(row, cols.min), sheet.Cells(row, cols.max))
      values = cells.Value
      cols.each do |col|
        if row.even?
          values.first[col] = 3
        else
          values.first[col] = 'こんにちは'
        end
      end
      cells.Value = values
    end
    %{Elapsed time: #{Time.now - start} secs}
  end
    
  define_method :exec do |book|
    bookname = File.basename((book).Name, ".*")
    send(bookname.to_sym, book, args[bookname.to_sym])
  end
  
  def alpha_to_num(alphas)
    tables = {}.tap{|h| ('A'..'Z').to_enum.with_index(1){|c, i| h[c]=i} }
    convertor = ->s{s.upcase.reverse.chars.with_index.inject(0){|r, (c,i)| r+=tables[c]*26**i}}
    result =  case alphas
              when String then  convertor[alphas]
              when Array  then  alphas.map(&convertor)
              when Range  then  Range.new(*alphas.map(&convertor).minmax)
              else              alphas
              end
  rescue
    exit(1)
  end
  
end

script = Script.new



.xlsxとか他のExcelバージョンでは動作確認していません。
環境がないので…

コマンドラインオプション:-Fregexp

ん?regexp??

-Fregexp

    入力フィールドセパレータ($;)に regexp をセットします。

引用:[http://doc.ruby-lang.org/ja/1.9.2/doc/spec=2frubycmd.html#cmd_option:title=コマンドラインオプション]

-Fって文字列指定だと思ってた。




ということは…(例が悪いけど)

rem CSV→TSV
echo "001","abc", "002" ,"あいう" ,  | ruby -F[\s,]+ -lane "puts $F.join(%{\t})"
"001"   "abc"   "002"   "あいう"

rem CSV→TSV(強引な二重引用符外し)
echo "001","abc", "002" ,"あいう" ,   | ruby -F[\s,\"]+ -lane "puts $F.drop(1).join(%{\t})"
001     abc     002     あいう



テキストファイル内の文字コード値表示とか。
テキストファイル [ CP932.txt / UTF-8N.txt ]

もうダメだ…
the end.
13895 days

文字コード値表示

rem CP932.txt
type CP932.txt| ruby -Ks -F\.? -alne "puts $F.map{|c| c.unpack('H*')}.join(' ')"
82e0 82a4 835f 8381 82be 8163
74 68 65 20 65 6e 64
31 33 38 39 35 20 64 61 79 73

rem UTF8N.txt
type UTF8N.txt| ruby -Ku -F\.? -alne "puts $F.map{|c| c.unpack('H*')}.join(' ')"
e38282 e38186 e38380 e383a1 e381a0 e280a6
74 68 65 20 65 6e 64
31 33 38 39 35 20 64 61 79 73

String#charsじゃね?ってツッコミはなしでw

Ruby Koans メモ

Ruby Koansが勉強になって面白いです

メモ(更新中)



object_id

共通

false.object_id # => 0 
true.object_id  # => 2 
nil.object_id   # => 4 

Windows XP
ruby 1.9.2p136 (2010-12-25) [i386-mingw32]

fixmin  = -2**30  # => -1073741824
fixmax  = 2**30-1 # => 1073741823
range   = -> base, width=1 { (base-width..base+width).to_a }
l_range = range[fixmin]
u_range = range[fixmax]
p nums  = l_range + u_range

fexpr   = -> num { num * 2 + 1}
cond    = -> expr, num { expr[num] == num.object_id }.curry
f_cond  = cond[fexpr]

nums.group_by(&f_cond)
# => {false=>[-1073741825, 1073741824], true=>[-1073741824, -1073741823, 1073741822, 1073741823]}

Mac OS X 10.6.6
ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin10]

fixmin  = -2**62  # => -4611686018427387904
fixmax  = 2**62-1 # => 4611686018427387903 
range   = -> base, width=1 { (base-width..base+width).to_a }
l_range = range[fixmin]
u_range = range[fixmax]
p nums  = l_range + u_range

fexpr   = -> num { num * 2 + 1}
cond    = -> expr, num { expr[num] == num.object_id }.curry
f_cond  = cond[fexpr]

nums.group_by(&f_cond)
# => {false=>[-4611686018427387905, 4611686018427387904], true=>[-4611686018427387904, -4611686018427387903, 4611686018427387902, 4611686018427387903]} 



Array#[]
self[start, length] -> Array | nil

  1. lenghtが負の時は nil
  2. startと配列サイズ以下で、かつlengthが0の場合は []
  3. startと配列サイズが等しい場合は [] (lengthは0以上)
  4. startと配列サイズより大きい場合は nil (lengthは0以上)
a = [ "a", "b", "c", "d", "e" ] 
a[0, -1]  # => nil 
a[0, 0]   # => [] 
a[0, 1]   # => ["a"] 
a[0, 2]   # => ["a", "b"] 
a[0, 10]  # => ["a", "b", "c", "d", "e"] 
a[4, -1]  # => nil 
a[4, 0]   # => [] 
a[4, 1]   # => ["e"] 
a[4, 2]   # => ["e"] 
a[4, 10]  # => ["e"] 
a[5, -1]  # => nil 
a[5, 0]   # => [] 
a[5, 1]   # => [] 
a[5, 2]   # => [] 
a[5, 10]  # => [] 
a[6, -1]  # => nil 
a[6, 0]   # => nil 
a[6, 1]   # => nil 
a[6, 2]   # => nil 
a[6, 10]  # => nil 

FizzBuzzはじめました

乗り遅れ気味だけどFizzBuzzやってみました。

[Ruby1.9.2p136]

1.upto(100){|i|puts"#{[:Fizz][i%3]}#{[:Buzz][i%5]}"[/.+/]||i}

61B

1.8.7で良いみたいなので100を?dにして・・・

[Ruby1.8.7p330]

1.upto(?d){|i|puts"#{[:Fizz][i%3]}#{[:Buzz][i%5]}"[/.+/]||i}

60B

私の力ではこれが限界です。式展開部のとこをどうにかならないかなぁ。

ところでトップは ・・・ ・・・ ・・・ 53B!!
ハンパねぇ、プロは凄すぎです。

golfは7打差、黄金聖闘士には3点足りず・・・はぁ〜、遠いなぁ〜〜

もっともっと勉強せねばーーー

てか、年度末かGW明けに仕事をうしないそうなので、そっちをどうにか
する方が先か(-_-;)