Rubyとの出会いを思い出した
irofさんのid:irof:20111203を読んで。
同感ですね〜!
思えば、同じ思い(「ブレイク処理」は正直論外で、分かり易く書くには?)がキッカケでRubyを知って、ハマっていった気がする。
当時、自分の使える言語ではスッキリしなくて、使ったことがない言語を試してたらRubyがドンピシャだった。
というか、全く使ったことなかったのに『こんな感じで書けたら〜』と気楽に書いてたら出来ちゃったし。
とにかくスッキリしちゃったので、使ったことがない言語での調査もそこで終了させちゃったw
てな感じで、記事を読んでたら思わずRubyと出会った頃を思い出しましたよ。
さて、当時よりわかりにくい気がするけど、今だとこう書きます。
Datum = Struct.new(:code, :name, :value) data = [ Datum.new("A01", "hoge", 100), Datum.new("A01", "piyo", 200), Datum.new("A02", "hoge", 300), Datum.new("A03", "hoge", 400), Datum.new("A03", "piyo", 500), ] p data.group_by{ |d| d.code }.tap{ |_| _.each{ |key, data| _[key] = data.inject(0){ |r, d| r+d.value } } } # => {"A01"=>300, "A02"=>300, "A03"=>900}
FizzBuzzコンバーター
最近FizzBuzz記事が多いですね。
ということで、私も乗っかってネタを一つ
ruby
# coding: UTF-8 class Converter def initialize @specs = [] end def specs( value , &cond ) @specs << lambda { |e| cond[e] ? value : nil } end def to_proc lambda { |e| conved = @specs.map{ |spec| spec[e] }.join conved.empty? ? e : conved } end end if __FILE__ == $0 ARGV[0] or raise "Requires an integer argument." max = ARGV[0].to_i fizzbuzz = Converter.new fizzbuzz.specs( "Fizz" ){ |n| n % 3 == 0 } fizzbuzz.specs( "Buzz" ){ |n| n % 5 == 0 } puts 1.upto(max).map(&fizzbuzz) end
追記:タイトルと関係ないけど、FizzBuzzメソッドチェイン
ruby
puts 1.upto(100).with_object(nil) .map { |n, o| ( o ||= [] ) << :Fizz if n % 3 == 0; [n, o] } .map { |n, o| ( o ||= [] ) << :Buzz if n % 5 == 0; [n, o] } .map { |n, o| ( o || [n] ) * "" }
お題:FizzBuzz
お題:FizzBuzz - No Programming, No Life
rubyで回答
1.upto(100){|i|puts"#{[:Fizz][i%3]}#{[:Buzz][i%5]}"[/.+/]||i}
お題:ある金額になるコインの組み合わせ
お題:ある金額になるコインの組み合わせ - No Programming, No Life
rubyで回答
# coding: CP932 require "rspec" def total_coins_pattern(total, *coins) total = total.to_i coins = [*coins].flatten min_coin = coins.min.to_i size = min_coin.zero? || total.zero? ? exit(false) : total / min_coin 1.upto(size).inject([]){|r, n| r + coins.repeated_combination(n).select{|c| c.inject(:+).eql?(total)} }.compact.sort end def total_coins_output(total, coins, &block) result = yield(total, coins) <<EOS コインの種類:#{coins.join(", ")} 金額:#{total} 組み合わせ数:#{result.count} 組み合わせ: #{result.map(&:to_s).join("\n").delete('"')} EOS end describe "total_coins_pattern" do context "with argument 1, [1]" do subject { total_coins_pattern(1, [1]) } it { should eq [[1]] } end context "coins [1, 5, 10, 50, 100, 500]" do let(:coins){[1, 5, 10, 50, 100, 500]} context "total 1" do subject { total_coins_pattern(1, coins) } it { should eq [[1]] } end context "total 4" do subject { total_coins_pattern(4, coins) } it { should eq [[1, 1, 1, 1]] } end context "total 5" do subject { total_coins_pattern(5, coins) } it { should eq [[1, 1, 1, 1, 1], [5]] } end context "total 6" do subject { total_coins_pattern(6, coins) } it { should eq [[1, 1, 1, 1, 1, 1], [1, 5]] } end context "total 10" do subject { total_coins_pattern(10, coins) } it { should eq [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 5], [5, 5], [10]] } end context "total 11" do subject { total_coins_pattern(11, coins) } it { should eq [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 5], [1, 5, 5], [1, 10]] } end end end describe "total_coins_output" do context "with argument 10, [1, 5, 10, 50, 100, 500], &block" do subject { total_coins_output(10, [1, 5, 10, 50, 100, 500]){|total, coins| total_coins_pattern(total, coins)} } it { should eq <<EOS } コインの種類:1, 5, 10, 50, 100, 500 金額:10 組み合わせ数:4 組み合わせ: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] [1, 1, 1, 1, 1, 5] [5, 5] [10] EOS end end __END__ total_coins_pattern with argument 1, [1] should == [[1]] coins [1, 5, 10, 50, 100, 500] total 1 should == [[1]] total 4 should == [[1, 1, 1, 1]] total 5 should == [[1, 1, 1, 1, 1], [5]] total 6 should == [[1, 1, 1, 1, 1, 1], [1, 5]] total 10 should == [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 5], [5, 5], [10]] total 11 should == [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 5], [1, 5, 5], [1, 10]] total_coins_output with argument 10, [1, 5, 10, 50, 100, 500], &block should == コインの種類:1, 5, 10, 50, 100, 500 金額:10 組み合わせ数:4 組み合わせ: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] [1, 1, 1, 1, 1, 5] [5, 5] [10]
お題:文字列を先頭から見て同じところまで除去
お題:文字列を先頭から見て同じところまで除去 - No Programming, No Life
rubyで回答
# coding: CP932 require "rspec" def shift_same_str(*args) args.map(&:chars).map(&:to_a).tap do |x| x.min_by(&:count).dup.each {|s| x.each(&:shift) if x.all?{|a| a.first.eql?(s)}} end.map!(&:join) end describe "shift_same_str" do context "with argument 'abcdef', 'abc123'" do subject { shift_same_str('abcdef', 'abc123') } it { should eq ['def', '123'] } end context "with argument 'あいうえお', 'あいさんさん', 'あいどる'" do subject { shift_same_str('あいうえお', 'あいさんさん', 'あいどる') } it { should eq ['うえお', 'さんさん', 'どる'] } end context "with argument '12345', '67890', '12abc'" do subject { shift_same_str('12345', '67890', '12abc') } it { should eq ['12345', '67890', '12abc'] } end end __END__ >rspec odai.rb -fd shift_same_str with argument 'abcdef', 'abc123' should == ["def", "123"] with argument 'あいうえお', 'あいさんさん', 'あいどる' should == ["うえお", "さんさん", "どる"] with argument '12345', '67890', '12abc' should == ["12345", "67890", "12abc"] Finished in 0.01562 seconds 3 examples, 0 failures
メモ:Enumerator
似てるけど大きな違い。メソッドが何を返すか気をつけよう。
Enumeratorオブジェクトを返すメソッドは、もっとあっても良いと思う。
id:ku-ma-meさんのmame/enumerabler · GitHubとか採用されるといいな。
# ruby 1.9.2p180 (2011-02-18) [i386-mingw32] num = 10 puts num.downto( 1 ).map{ |n| "*" * n } # Case.1 num.downto( 1 ).map{ |n| puts "*" * n } # Case.2 num = 2**16 #puts num.downto( 1 ).map{ |n| "*" * n } # => `*': failed to allocate memory (NoMemoryError) #num.downto( 1 ).map{ |n| puts "*" * n } # Case.2 num = 10 # Case.1 enum = num.downto( 1 ).map fmt = lambda{ |n| "*" * n } data = enum.each( &fmt ) puts data # Case.2 enum = num.downto( 1 ).map out = lambda{ |n| puts "*" * n } enum.each( &out ) num = 2**16 # Case.1 #enum = num.downto( 1 ).map #fmt = lambda{ |n| "*" * n } #data = enum.each( &fmt ) # => `*': failed to allocate memory (NoMemoryError) #puts data # Case.2 #enum = num.downto( 1 ).map #out = lambda{ |n| puts "*" * n } #enum.each( &out )
RubyとWSHでユーザー環境変数を設定する
チクタク…チクタク…
# coding: CP932 module OLE require "win32ole" module Environment MEMBERS = { HTTP_PROXY: [ [ :protocol, :username, :password, :host, :port ], %r{^(.*?)//(.*?):(.*?)@(.*?):(.*?)$}, lambda{ |values| "%s//%s:%s@%s:%s"%values }, ], } module User class << self def [](name) wsh = WIN32OLE.new("WScript.Shell") obj = wsh.Environment(self.name.split(/::/).last.capitalize) variable(obj, name) end def variable(obj, name) attrs, pattern, format = *MEMBERS[name.to_sym] Struct.new(name, *attrs) do define_method( :name ) { name } define_method( :value ) { values.join.empty? ? nil : format[values] } define_method( :show ) { puts value } define_method( :load ) { members.zip( obj[name].scan(pattern).flatten ).each{ |m, v| self[m] = v } ; self } define_method( :save ) { value ? obj[name] = value : remove ; self } define_method( :remove ) { load && obj.Remove(name) } end end end end end end http_proxy = OLE::Environment::User["HTTP_PROXY"].new http_proxy.load.show # => http_proxy.protocol = "http:" http_proxy.username = "username" http_proxy.password = "password" http_proxy.host = "proxy.host.ne.jp" http_proxy.port = "8080" http_proxy.show # =>http://username:password@proxy.host.ne.jp:8080 http_proxy.save http_proxy.load.show # =>http://username:password@proxy.host.ne.jp:8080 http_proxy.password = http_proxy.password.reverse http_proxy.port = http_proxy.port[0,3] << "8" http_proxy.show # =>http://username:drowssap@proxy.host.ne.jp:8088 http_proxy.save http_proxy.load.show # =>http://username:drowssap@proxy.host.ne.jp:8088