たのしいRuby第1版練習問題回答 そのに
第12章 Stringクラス
(3)StringIOはめんどくさかったので割愛。
(1)kan2num.rb
#!ruby -Ks def kan2num(string) kan_digit_tbl = { '一' => 1, '二' => 2, '三' => 3, '四' => 4, '五' => 5, '六' => 6, '七' => 7, '八' => 8, '九' => 9 } factor_tbl = { '千' => 1000, '百' => 100, '十' => 10 } n = 0 str = string.strip until str.empty? case str when /\A(.*?)(#{factor_tbl.keys.join('|')})/o n += kan_digit_tbl[$1.empty? ? '一' : $1] * factor_tbl[$2] when /\A.*?\Z/ n += kan_digit_tbl[$&] end str = $' end n end if __FILE__ == $0 p kan2num('七千百二十三') end
(2)num2astrisk.rb
def num2astrisk(num) tbl = { '0' => '', '1' => '*', '2' => '**', '3' => '***', '4' => '****', '5' => '*****', '6' => '******', '7' => '*******', '8' => '********', '9' => '*********' } buf = '' String(num).split(//).each do |n| buf = #carry-up buf + buf + buf + buf + buf + buf + buf + buf + buf + buf tbl.has_key?(n) or break buf += tbl[n] end buf end if __FILE__ == $0 puts '@' * 32 puts num2astrisk(32) end
OrderedHash
Hashクラスの章の練習問題から。テストしてないけどほぼ本家Hashと同じ
インタフェースを揃えてみた。
Hashの章の練習問題なのにalistで実装したらダメじゃん、という問題には
書き終わった後に気づいた。
# Ordered Hash class # for Ruby1.8 forward # class OrderedHash include Enumerable Upper19 = Object.const_defined?('KeyError') def initialize(ifnone=nil, &block) @body = [] if block_given? ifnone.nil? or raise ArgumentError, 'wrong number of argumrnts.' @default_proc = block end @default = ifnone end attr_reader :body protected :body private def ifnone(key) if default_proc default_proc.call(self, key) else @default end end def fetch_none(key, default, &block) if block_given? default.nil? or warn 'warning: block superdedes default value argument' yield(key) else unless default.nil? klass = Upper19 ? KeyError : IndexError raise klass, 'key not found' end default end end public # Indexer def [](key) body.assoc(key)[1] or ifnone(key) end def []=(key, value) hit = body.assoc(key) if hit hit[1] = value else body << [key, value] end end def fetch(key, default=nil, &block) body.assoc(key)[1] or fetch_none(key, default, &block) end alias store []= # Element attr_reader :default_proc def default(key=nil) if default_proc key.nil? ? nil : default_proc.call(self, key) else @default end end def default=(v) @default_proc = nil @default = v end def keys body.map{|k, v| k } end def values body.map{|k, v| v } end def key(value) hit = body.rassoc(value) ? hit[0] : nil end def index(value) warn 'warning: Hash#index is deprecated; use Hash#key' if Upper19 key(value) end def values_at(*keys) keys.map{|key| self[key] } end def indexes(*keys) warn 'warning: Hash#indexes is deprecated; use Hash#values_ati' values_at(*keys) end def indices(*key) warn 'warning: Hash#indices is deprecated; use Hash#values_ati' values_at(*keys) end def invert h = self.class.new each do |k, v| h[v] = k end h end def size body.size end alias length size # Iterator def each body.each{|k, v| yield(k, v) } end alias each_pair each def each_key body.each{|k, v| yield(k) } end def each_value body.each{|k, v| yield(v) } end # Distincter def empty? body.empty? end def key?(k) body.assoc(k) ? true : false end alias has_key? key? alias include? key? alias member? key? def value?(v) body.rassoc(v) ? true : false end alias has_value? value? # Converter def to_a body.dup end def to_hash if default_proc hsh = Hash.new{|h, k| default_proc.call(h, k) } else hsh = Hash.new(@ifnone) end each{|k, v| hsh[k] = v } hsh end # HandleInner def rehash self end def replace(other) @body = other.body.dup self end def clear body.clear self end def shift empty? ? ifnone(nil) : body.shift end def delete(key) idx = nil body.each_with_index do |entry, i| if key == entry[0] idx = i ; break end end if idx body.delete_at(idx) else block_given? ? yield(key) : nil end end def delete_if(&block) reject!(&block) self end def reject! targets = [] body.each_with_index do |entry, i| yield(entry[0], entry[1]) and targets << i end unless targets.empty? targets.each{|i| body.delete_at(i) } self end end def update(other) other.each do |k, v| self[k] = block_given? ? yield(k, self[k], v) : v end end alias merge! update def merge(other) dup.merge!(other) end end if __FILE__ == $0 [Hash, OrderedHash].each do |klass| h = klass.new h['hoge'] = 'piyo' h[:foo] = :bar h['ruby'] = :wonderful h.each do |k, v| p k, v end puts '-'*60 end #puts(Hash.instance_methods - OrderedHash.instance_methods) end