slice_beforeで

id:seuzoさんの『連続した日付を範囲形式でまとめる』を読んで自分も作ってみた。

いつまでも使い方が覚えられないEnumerable#slice_beforeを使ってみる。

Ruby1.9.2p136です。

# coding: UTF-8
require 'date'

lists   = " 2010-12-31 , 2011-01-01  ,  2011-01-02 ,2011-01-10, 2011-03-02,2011-03-01,2011-02-28,2011-03-03,2011-03-05,2012-0-00 "
sorted  = [*lists].flatten.flat_map{|list| list.chomp.split(/,/)}
                          .map{|e| Date.parse(e.strip) rescue nil}.compact.sort

prev = sorted.first
result  = sorted.slice_before{|cur| prev, prevprev = cur, prev; prevprev.succ != prev}
                .map{|a| a.minmax.uniq.map{|e| e.strftime("%m/%d")}.join("".encode(Encoding.find("locale")))}
                .join("".encode(Encoding.find("locale")))
puts result
# =>12/31〜01/02、01/10、02/28〜03/03、03/05

数値もやってみる。

# coding: UTF-8

def list2array(*lists, list_delimiter)
  [*lists].flatten.flat_map{|list| list.chomp.split(list_delimiter).map(&:strip)}
end

def array_of(array, converter)
  array.map(&converter).compact.sort
end

def to_rangef(array, formatter)
  prev = array.first
  groups = array.slice_before do |cur|
    prev, prevprev = cur, prev
    prevprev.succ != prev
  end
  groups.map(&formatter)
end

if __FILE__ == $0
  
  lists = DATA.lines.to_a
  
  list_delimiter = /,/
  array = list2array(lists, "11.1,12.3,13.5,14.7,15.9", list_delimiter)
  
  converters = {
    Date:   lambda{|e| require 'date'; Date.parse(e) rescue nil},
    Fixnum: lambda{|e| e.to_i.zero? ? (Integer(e) rescue nil) : e.to_i},
    String: lambda{|e| e.to_s rescue nil},
  }
  array = array_of(array, converters[:Fixnum])
  
  formatters = {
    Date:   lambda{|a| require 'date'; a.minmax.uniq.map{|e| e.strftime("%m/%d")}.join("..")},
    Fixnum: lambda{|a| a.minmax.uniq.map(&:to_s).join("..")},
    String: lambda{|a| a.minmax.uniq.map{|e| %!"%s"!%e}.join("..")},
  }
  groups = to_rangef(array, formatters[:Fixnum])
  
  delimiter = "".encode(Encoding.find("locale"))
  puts groups.join(delimiter)
# =>0..2、4..7、9..15  
end

__END__
1,2,4
6
5
7.0,9.0,10
0
a, ?a

眠くてGiveUp(-_-)zzz

ちょっとハマった上に無駄骨だった

環境変数http_proxyをURI.parseした時の要素が気になって、調べるコードを書いてみた。

最初はこんな感じのコード

require 'uri';{}.tap{|h|
URI.parse(ENV['http_proxy']||ENV['HTTP_PROXY']||'').tap{|uri|
uri.instance_variables.each{|var| h[var]||=uri.instance_variable_get(var)}}}

もっとシンプルな方法があるはずとリファレンスをみる。
URI::Generic#select(*components)とURI::Generic.componentを見つける!
早速、使ってみた。

require 'uri'

uri = URI.parse( ENV['http_proxy'] || ENV['HTTP_PROXY'] || '' )
components = URI::Generic.component

uri.select(*components)
# => ArgumentError: expected of components of URI::HTTP (scheme, userinfo, host, port, path, query, fragment)

ダメじゃん。なして?

要素を確認。

URI::Generic.component
# => [:scheme, :userinfo, :host, :port, :registry, :path, :opaque, :query, :fragment]

なぬ?
URI::Generic.componentで取得できる要素とURI::Generic#selectが受け付ける
要素が違うじゃん。

余分な要素を抜いてみた。

require 'uri'

uri = URI.parse( ENV['http_proxy'] || ENV['HTTP_PROXY'] || '' )
components = URI::Generic.component - [:registry, :opaque]

uri.select(*components)
# => ["http", "user:password", "proxy.hoge.co.jp", 8080, "", nil, nil]

これでいいのか〜

んじゃ、最初のを書き直して・・・(上下は同じ結果)

require 'uri';{}.tap{|h|
(URI::Generic.component-[:registry,:opaque]).tap{|c| h.merge!(Hash[*c.zip(URI.parse(ENV['http_proxy']||ENV['HTTP_PROXY']||'').select(*c)).flatten])}}
require 'uri';{}.tap{|h| (URI::Generic.component-[:registry,:opaque]).tap{|c| c.zip(URI.parse(ENV['http_proxy']||ENV['HTTP_PROXY']||'').select(*c)).each{|k,v|
h[k]||=v}}}

最初のより長くなってるし、要素の意味も全くわかっていない(>_<)

要素の意味は後で調べよう。

コマ大数学科

1から10000までの番号がついた電灯がある。1の倍数の電灯のスイッチを押し、次に2の倍数のスイッチを押し、次に3の倍数のスイッチを押し…と、これを10000回行った後、点灯している電灯の数はいくつか。初期状態で電球は消灯している。(コマ大数学科第12回・改) #math

自分の回答。

require 'mathn';(2..10000).map{|n| Prime.prime_division(n)}.count{|v| v.all?{|a| a.last.even?}}+1

模範回答。なるほど〜

->m{(1..m).count{|n| n*n<=m}}[10000]

04灘中

A,B,C3種類のコインがあり、A6枚、B1枚、C1枚の重さと、A1枚、B4枚、C1枚の重さと、A1枚、B1枚、C3枚の重さはいずれも61gである。C1枚の重さはいくらか。(04灘中) #arithmetic

140文字に収まらなかった。

(1..59).to_a.repeated_permutation(3).find{|v| [[6,1,1],[1,4,1],[1,1,3]].inject([]){|r,a| r<<->v{v.zip(a).inject(0){|r,(x,y)| r+=x*y}==61}}.all?{|p| p[v]}}[2]

File.readlines - 私が悪かった。

メール投稿

前とはコードが違うけどファイルのサイズで落ちたり落ちなかったり
したのだけど・・・

#!ruby -Ku
# coding: UTF-8

DAT = "1234567890"*100
MB = 1024

# 0:128MB, 1:256MB, 2:512MB, 3:1GB
PAT = 3..3

PAT.map{|n| 128 * 2**n }.each do |size|

	fname = "#{size}mb.dat"
	fmt = lambda{|title| "%s %s %s %s %s"%["="*5, fname, title, Time.now, "="*5]}
	
	File.open(fname, "w") do |fp|
		(size*MB).times do |n|
			fp.puts %!#{"%021d:"%n}#{DAT}!
		end
	end unless test(?f, fname)

	puts fmt.call("StartTime".center(12))
	puts
	puts "#{fname} is #{File.readlines("#{size}mb.dat").size.to_s.rjust(8)} recodes."
	puts
	puts fmt.call("EndTime".center(12))
	puts

	`del #{fname}`

end

前はコーディングが悪かったんだな。きっと。

Windowsで複数のRubyバージョンを使うならpik

rvmよりもpikが好き!

pik for osxがほしい!

[2011.03.05 追記:pik 0.2.8]

Rubyがインストールされていない場合

Ruby+pikインストーラー[msi]でインストール

msiexec /i http://github.com/downloads/vertiginous/pik/pik-0.2.8.msi

Rubyがインストールされている場合

pik[gem]をインストール
gem install pik

pikを使う

pikを(インストール先を指定して)インストール
pik_install c:\pik

pathが通っているかを確認

path

pathが通っていなかったら通してね

Rubyのインストール先を指定

Rubyのインストール先も指定できます

pik config install_dir=c:\pik
Ruby各バージョンの簡単インストール

簡単インストール可能なRubyを確認
Ruby,JRuby,IronRubyなどなど

pik ls -r

使いたいバージョンをインストール

pik install Ruby 1.9.2-p180
pik install Ruby 1.8.7-p334
インストール済バージョンをpikで管理

pikの簡単インストールを利用せずにインストールしたRubyも
pik管理下にできます

pik add [<追加したいRubyフォルダのパス>\bin]

DevKit

DevKitのインストール先を指定

DevKitのインストール先も指定できます

pik config devkit=c:\pik
pik devkit update
DevKitをインストール
pik install devkit
インストール済のRubyを一覧表示
pik ls -v

Gem

Ruby切り替え

Ruby1.8.7p334に変更

pik 187
Gemアップデートとインストール

ここでは便利なtappをインストール

gem update --system
gem install tapp --no-rdoc --no-ri
gem list
Ruby切り替え

Ruby1.9.2p180に変更

pik 192
Gemの同期

Ruby1.9.2p180のGemをRuby1.8.7p334のGemと同じにする

gem list
pik gemsync
[コピー元を選択 例:2. 187: ruby 1.8.7(2011-02-18 patchlevel 334)]
? 2
gem list
Gemの一括インストール

全てのインストール済RubyにGemをインストールできる

pik gem list
pik gem install rspec --no-rdoc --no-ri

pikその他

一括実行

色々あります

pik bench fib.rb
pik ruby fib.rb
pik rb -e 'puts RUBY_VERSION'
pik run PATH

fib.rb

cache = { 0 => 0, 1 => 1 }
fib = lambda {_fib_ = lambda {|n| cache[n] ||= _fib_[n-2] + _fib_[n-1]}}.call
(1..10000).each { |e| "#{fib[e] }" }

pik bench fib.rbを実行してみた

pik bench fib.rb
IronRuby 1.1.2.0 on .NET 4.0.30319.1

Rehearsal ------------------------------------------------------------
** benchmarking 'fib.rb'   3.447622   0.000000   3.447622 (  3.437196)
--------------------------------------------------- total: 3.447622sec

                               user     system      total        real
** benchmarking 'fib.rb'   3.416422   0.000000   3.416422 (  3.409195)

jruby 1.6.0.RC2 (ruby 1.8.7 patchlevel 330) (2011-02-09 5434c72) (Java HotSpot(TM) Client VM 1.6.0_24) [Windows 7-x86-java]

Rehearsal ------------------------------------------------------------
** benchmarking 'fib.rb'   6.419000   0.000000   6.419000 (  6.401000)
--------------------------------------------------- total: 6.419000sec

                               user     system      total        real
** benchmarking 'fib.rb'   6.328000   0.000000   6.328000 (  6.328000)

ruby 1.8.7 (2011-02-18 patchlevel 334) [i386-mingw32]

Rehearsal ------------------------------------------------------------
** benchmarking 'fib.rb'   4.804000   0.000000   4.804000 (  4.802275)
--------------------------------------------------- total: 4.804000sec

                               user     system      total        real
** benchmarking 'fib.rb'   4.789000   0.016000   4.805000 (  4.825276)

ruby 1.9.2p180 (2011-02-18) [i386-mingw32]

Rehearsal ------------------------------------------------------------
** benchmarking 'fib.rb'   2.215000   0.000000   2.215000 (  2.220127)
--------------------------------------------------- total: 2.215000sec

                               user     system      total        real
** benchmarking 'fib.rb'   2.231000   0.000000   2.231000 (  2.231127)







[2010.06.27]
gem install pik --platform x86-mswin32
pik_install c:\pik
※ pathは通しておきましょう
pik -v # pik 0.2.8
pik ls -r
pik install IronRuby 1.0v4 # need .NET Framework4
pik install Ruby 1.9.1-p378-1
pik install Ruby 1.9.2dev-preview3-1
※ 7-Zipでコケたら
http://sourceforge.net/projects/sevenzip/files/7-Zip/4.65/7za465.zip/downloadを解凍して
pikのディレクトリの7za.exeを上書きする

現在のメソッド名取得とメソッド名 #{ruby}

現在のメソッド名取得:__method__, __callee__
メソッド名での実行:__send__

前回、前々回と投稿したメソッドはこんな感じにも実装できる。

class String

  def centerb(width, padding = ' ')
    justb(__method__, width, padding)
  end

  def rjustb(width, padding = ' ')
    justb(__method__, width, padding)
  end

  def ljustb(width, padding = ' ')
    justb(__method__, width, padding)
  end

  private
  def justb(method_symbol, width, padding)
    __send__(method_symbol.to_s.chop, width-(bytesize-size), padding)
  end

end