演習問題解答例

演習問題 1

既存の Array に変更を加える方法と、新しく Array を作る方法で [0, 1, 2, 3] という Array を作ろうという問題。

a = []
b = a
b               # => []
a.object_id     # => 134275960
4.times{|i| a[i] = i}
a               # => [0, 1, 2, 3]
a.object_id     # => 134275960
b               # => [0, 1, 2, 3]
  • Array#[]= で Array オブジェクトを変更する例。
  • object_id が等しいので既存のオブジェクトの変更。
  • b の指すオブジェクトも変わってるんで、既存のオブジェクトの変更。
a = []
b = a
b               # => []
a << 0 << 1 << 2 << 3
b               # => [0, 1, 2, 3]
  • 「くく」で変更する例。
a = []
b = a
b               # => []
a[0, 4] = *0..3
b               # => [0, 1, 2, 3]
  • Array#[]= に位置とサイズを指定して代入する例。
a = []
b = a
b               # => []
a[0..3] = *0..3
b               # => [0, 1, 2, 3]
  • Array#[]= に Range を指定して代入する例。

後は新しく Array オブジェクトを作る例。

[*0..3]                         # => [0, 1, 2, 3]
(0..3).to_a                     # => [0, 1, 2, 3]
%w[0 1 2 3].map(&:to_i)         # => [0, 1, 2, 3]
"0123".split(//).map(&:to_i)    # => [0, 1, 2, 3]
Array.new(4){|i| i}             # => [0, 1, 2, 3]
4.times.to_a                    # => [0, 1, 2, 3]

たぶん、みんなも、もっと変態な例を思いついたはず。

会場でピックアップできればよかったなぁ。

演習問題 2

文字列の単語を数える。文字を数える。

まずは単語

def wc(a)
  a.inject(Hash.new{|h, k| h[k] = 0}) do |s, i|
    s[i] += 1
    s
  end
end

wc("No Ruby, No Life.".scan(/\p{Word}+/))
  .sort_by{|w, n| -n}
  .each{|i| puts "%8d %s" % i.reverse}

# >>        2 No
# >>        1 Ruby
# >>        1 Life
  • 文字列は適当。
  • String#scan で単語を抽出
  • Array#sort_by で語数の降順

つづいて文字

sum = wc("No Ruby, No Life.".split(//))
(" ".."~").to_a.each_slice(8) do |line|
  puts line.map{|c| "%s(%2d)" % [c, sum[c]]}.join(' ')
end

# >>  ( 3) !( 0) "( 0) #( 0) $( 0) %( 0) &( 0) '( 0)
# >> (( 0) )( 0) *( 0) +( 0) ,( 1) -( 0) .( 1) /( 0)
# >> 0( 0) 1( 0) 2( 0) 3( 0) 4( 0) 5( 0) 6( 0) 7( 0)
# >> 8( 0) 9( 0) :( 0) ;( 0) <( 0) =( 0) >( 0) ?( 0)
# >> @( 0) A( 0) B( 0) C( 0) D( 0) E( 0) F( 0) G( 0)
# >> H( 0) I( 0) J( 0) K( 0) L( 1) M( 0) N( 2) O( 0)
# >> P( 0) Q( 0) R( 1) S( 0) T( 0) U( 0) V( 0) W( 0)
# >> X( 0) Y( 0) Z( 0) [( 0) \( 0) ]( 0) ^( 0) _( 0)
# >> `( 0) a( 0) b( 1) c( 0) d( 0) e( 1) f( 1) g( 0)
# >> h( 0) i( 1) j( 0) k( 0) l( 0) m( 0) n( 0) o( 2)
# >> p( 0) q( 0) r( 0) s( 0) t( 0) u( 1) v( 0) w( 0)
# >> x( 0) y( 1) z( 0) {( 0) |( 0) }( 0) ~( 0)
  • String#split で文字に分解
  • Enumerable#each_slice で、8文字ごとに表示*1

もっといいのがあったら教えて!

*1:ASCII のみだけど