たのしいRuby第1版練習問題回答
Stringは後回し。
追記
- 2007-11-18 celsius.rbを修正
■第10章 Numericクラス
(1)fahr2celsius.rb
def fahr2celsius(f) 5.0 * (f - 32.0) / 9.0 end if __FILE__ == $0 printf("%11s %11s\n", 'Fahr', 'Celsius') 0.step(100, 5) do |fahr| printf("%11.6f %11.6f\n", fahr, fahr2celsius(fahr)) end end
(2)celsius.rb
class Celsius def initialize(c) @value = c.to_f end attr_reader :value protected :value def fahr2celsius(f) 5.0 * (f - 32.0) / 9.0 end private :fahr2celsius def to_celsius value end def to_fahr fahr2celsius(value) end def +(other) self.class.new(value + other.value) self end end if __FILE__ == $0 c1 = Celsius.new(27.3) c2 = Celsius.new(50) c12 = c1 + c2 [c1, c2, c12].each do |c| p c.to_celsius p c.to_fahr end end
(3)prime_p.rb
def prime?(num) num > 1 && (2 ... num).select{|x| (num % x).zero? }.empty? end if __FILE__ == $0 0.upto(9) do |n| p n if prime?(n) end end
(4)round_diff.rb
#doubt a = 0.1 + 0.2 p a b = (a == 0.3) p b #answer [a, 0.3].each do |x| printf("%.64f\n", x) end
■第11章 Arrayクラス
(1)square.rb
def main if __FILE__ == $0 nums = [1, 2, 4, 6] p square(nums) puts '-'*60 end end # # # # # def square(nums) nums.collect{|n| n * n } end main def square(nums) sq = [] nums.each{|n| sq.push(n * n) } sq end main def square(nums) sq = [] i = 0 until i == nums.size sq.push(nums[i] ** 2) i += 1 end sq end main
(2)sum_array.rb
def sum_array(nums1, nums2) if nums2.size > nums1.size nums1, nums2 = nums2, nums1 end nums1.zip(nums2).map{|x, y| x + (y || 0) } end if __FILE__ == $0 p sum_array([1, 2, 3], [4, 6, 8]) end
(3)balanced_p.rb
def balanced?(parens) tbl = { '(' => ')', '{' => '}', '[' => ']' } stack = [] parens.each do |x| case when tbl.key?(x) stack.push(x) when tbl.value?(x) tbl[stack.pop] == x or return false end end stack.empty? end if __FILE__ == $0 parens1 = '({{}()}())'.split(//) parens2 = '({{}(}))'.split(//) [parens1, parens2].each do |parens| p balanced?(parens) end end
■第13章 Hashクラス
(1)str2hash.rb
def str2hash(str) h = {} temp = str.strip.split(/\s+/) until temp.empty? k = temp.shift v = temp.shift h[k] = v if k end h end if __FILE__ == $0 $KCODE = 'sjis' p str2hash("blue 青 while 白\nread 赤") end
(2)orderedhash.rb
class OrderedHash include Enumerable def initialize @body = [] end attr_reader :body protected :body def each(&block) body.each(&block) end def [](key) body.assoc(key)[1] end def []=(key, value) hit = body.assoc(key) if hit hit[1] = value else body << [key, value] end end def key?(k) body.assoc(k) ? true : false end def value?(v) body.rassoc(v) ? true : false 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 end
■第14章 Regexpクラス
(1)mail_addr.rb
addr = 'shionist@yahoo.co.jp' /\A(.*?)@(.*?)\Z/ =~ addr local, domain = $1, $2 puts "local: #{$1}" puts "domain: #{$2}"
(2)gsub.rb
#!ruby -Ks str = "オブジェクト指向は難しい! なんて難しいんだ!" puts str puts str.gsub(/難しい(んだ)?/){|m| "簡単#{$1 ? 'なん' : ''}だ" }
(3)word_capitalize.rb
def word_capitalize(str) str.split('-').map{|w| w.gsub(/[a-zA-Z]+/){|m| m.capitalize } }.join('-') end if __FILE__ == $0 ['in-reply-to', 'X-MAILER'].each do |s| p word_capitalize(s) end end
■第15章 IOクラス
(1)copy.rb
def copy(from, dest) File.open(from, 'rb') do |f| File.open(dest, 'wb') do |w| w.print f.read end end end if __FILE__ == $0 copy $0, "#{$0}.copy~" end
(2)tail.rb
def tail(n, file) queue = [] IO.foreach(file) do |line| queue << line queue.shift if queue.size > n end puts queue end if __FILE__ == $0 tail(3, $0) end
■第16章 FileクラスとDirクラス
(1)printlibrary.rb
require 'rbconfig' def print_library exts = ['rb', Config::CONFIG['DLEXT'], Config::CONFIG['DLEXT2']] puts $:.map{|path| Dir.entries(path).select{|file| File.file?(File.join(path, file)) and exts.include?(file.split('.').last) } } end alias printLibrary print_library if __FILE__ == $0 printLibrary end
(2)dircopy.rb
require 'find' require 'fileutils' def dircopy(from, dest) from, dest = [from, dest].map{|dir| m = dir.match(/#{File::SEPARATOR}\Z/o) m ? m.pre_match : dir } Find.find(from) do |path| next unless File.directory?(path) FileUtils.mkpath( File.join(dest, path.match(/\A#{from}/).post_match) ) end Find.find(from) do |path| next if File.directory?(path) FileUtils.cp( File.join(from, path.match(/\A#{from}/).post_match), File.join(dest, path.match(/\A#{from}/).post_match) ) end end if __FILE__== $0 dircopy './From/', './Dest' end
(3)du.rb
require 'find' def du_sub(dir) total = 0 Dir.foreach(dir) do |path| next if path == '.' || path == '..' path = File.join(dir, path) if File.directory?(path) total += du_sub(path) else total += File.size(path) end end total end def du(dir) puts du_sub(dir) end if __FILE__ == $0 du('..') end
■第17章 Timeクラス
(1)jparsedate.rb
#!ruby -Ks def jparsedate(str) Time.local( *str.gsub(/(午前|午後)/){|m| { '午前' => '00+', '午後' => '12+' }[m] || '' }.scan(/[\d\+]+\D/s).map{|x| n = 0 if /\A[\d\+]+/ =~ x n += eval($&) end n } ) end if __FILE__ == $0 t = jparsedate("2001年12月23日午後8時17分50秒") puts t.strftime("%Y/%m/%d %H:%M:%S") end
(2)ls_t.rb
def ls_t(dir) puts (Dir.entries(dir) - ['.', '..']).map{|path| File.join(dir, path) }.sort{|x, y| File.ctime(y) <=> File.ctime(x) } end if __FILE__ == $0 ls_t('.') end