hyoromoのブログ

最近はVRSNS向けに作ったものについて書いています

たのしいRuby 第11章 練習問題(P.211)

今回は配列関係の練習問題。

(1)「1から100までの整数を含む配列を作れ」

a = Array.new(100) { |i| i+1 }
p a

これは簡単。

公式解答はこちら。

ary = []
100.times{|i| ary[i] = i + 1 }




(2)「(1)の配列の要素を全て100倍にせよ」

a = Array.new(100) { |i| i+1 }
b = a.collect { |i| i * 100 }
p b

まだ大丈夫。

公式解答はこちら。

# 配列を作成する
ary = (1..100).to_a

# 配列の全ての要素を100倍した値を含む新しい配列を作る
ary2 = ary.collect{|i| i * 100 }
p ary2

# 配列の全ての要素を100倍する
ary.collect!{|i| i * 100 }
p ary




(3)「(1)の配列から3の倍数だけを抽出せよ」

a = Array.new(100) { |i| i+1 }
a.reject! { |i| (i % 3) != 0 }
p a

reject でなくとも、delete_ifメソッドでも可能なハズです。

こちらが公式解答。

# 配列を作成する
ary = (1..100).to_a

# aryから3の倍数だけを取り出す
ary2 = ary.select{|i| i % 3 == 0 }
p ary2

# aryから3の倍数以外の数を削除する
ary.reject!{|i| i % 3 != 0 }
p ary

削除せず、取り出すだけなら select を使用するようですね。


(4)「(1)の配列を逆順に並べ替えよ」

a = Array.new(100) { |i| i+1 }
b = a.sort { |a,b|
  b <=> a
}
p b

「<=>」記号の意味は、左右のオブジェクトを比較し
「<」の場合はマイナス、「=」の場合は0、「>」の場合はプラスとなります。

公式解答はこちらとなります。

ary2 = ary.sort{|a, b| -(a <=> b) }
p ary2




(5)「(1)の配列に含まれる整数の合計値を求めよ」

a = Array.new(100) { |i| i+1 }
sum = 0

sum = a.inject(0) { |i, j|
  i + j
}

p sum

メソッドの説明:inject(初期値){|先頭要素, 2番目の要素| ... }
個人的にはeachを使ったほうが分かりやすいですね。

公式解答はこちら。

# 配列を作成する
ary = (1..100).to_a

# (a) Array#eachで和を求める
result = 0
ary.each{|i| result += i }
p result

# (b) Array#injectで和を求める
p ary.inject(0){|memo, i| memo += i }

私のやり方でも、公式のやり方でも結果は同じようです。


(6)乱数メソッドを使い、(1)の配列をでたらめに並べ替えよ」

a = Array.new(100) { |i| i+1 }

100.times do |i|
  str = a[i]
  a.delete_at(i)
  a[rand(99), 0] = a[i]
end

p a

一つ一つ取り出し、ランダムに挿入するよう組みました。
ここら辺から問題が難しくなってきましたね。。。

公式解答はこちら。

# 配列を作成する
ary = (1..100).to_a

# randを使って配列をかき混ぜる
ary2 = ary.sort_by{|i| rand }
p ary2

こんな簡単にランダムソートができるだなんて!
でも、sort_byメソッドの使い方がよく分からない。。。また今度じっくりと調べてみようか。


(7)「(1)の配列から、1〜10, 11〜20, 21〜30 といった10個の要素を含む配列を10個取り出しなさい」

any = Array.new(100) { |i| i+1 }
result = Array.new
10.times { |i|
  result << any[i*10..(((i+1)*10)-1)]
}

p result

なんか無理やりだな〜とは思ってます。

公式解答はこちら。

# 配列を作成する
ary = (1..100).to_a
result = Array.new
10.times{|i|
  result << ary[i*10, 10]
}
p result

あぁ、なるほど個数指定ですか。スマートに書けたのですね。


(7)「数値からなる配列 nums1 と nums2 に対し、個々の要素を足し合わせるメソッド sum_array を定義せよ」

def sum_array(nums1, nums2)
  result = []
  nums1.zip(nums2) { |a, b|
    result << a + b
  }
  return result
end

p sum_array([1,2,3], [4,6,8])

単純に「+」だと、配列を結合する意味になるため。zipメソッドを使用する。

公式解答はこちら。

def sum_array(ary1, ary2)
  result = Array.new
  ary1.zip(ary2){|a, b| result << a + b }
  return result
end

p sum_array([1, 2, 3], [4, 6, 8])




(8)「(,),{,} という4つの文字を要素とした配列があります。この配列に対し、カッコが正しく対応しているかをチェックするメソッドを定義せよ。
カッコが正しいか判断する条件として以下のようになっている。
・( と ) の数が同じ
・{ と } の数が同じ
・「( )」の対応と「{ }」の対応が交差することがない

def balanced?(ary)
  h = {"{" => "}", "(" => ")"}
  alpha = []
  ary.each{|c|
    if(c == "(" || c == "{")
      alpha.push(c)
    else
      str = h.fetch(alpha.pop)
      if(str != c)
        return false
      end
    end
  }
  
  # 括弧の数が合ってなかったかをチェック
  if alpha.length != 0
    return false
  end
  return true
end

p balanced?(["(", "{", "{", "}", "(", ")", "}", "(", ")", ")"])
p balanced?(["(", "{", "{", "}", "(", "}", ")", ")"])

工夫で頑張りました。公式解答とは一致してないでしょうね。

def balanced?(array)
  stack = Array.new()
  array.each{|elem|
    case elem
    when '('
      stack.push(elem)
    when '{'
      stack.push(elem)
    when ')'
      prev_elem = stack.pop
      if prev_elem != '('
        return false
      end
    when '}'
      prev_elem = stack.pop
      if prev_elem != '{'
        return false
      end
    else
      return false
    end
  }

  if stack.empty?
    return true
  else
    return false
  end
end

p balanced?([])                   #=> true
p balanced?(["(",")"])            #=> true
p balanced?(["{","(",")","}"])    #=> true
p balanced?(["{","(",")"])        #=> false
p balanced?(["(",")","}"])        #=> false

p balanced?(["(", "{", "{", "}", "(", ")", "}", "(", ")", ")"]) #=> true
p balanced?(["(", "{", "{", "}", "(", "}", ")", ")"])           #=> false

公式のほうがスマートですし、安定したプログラムですね。
どうやら私のやり方ですと、key が取得できない際にエラーになってしまうようです。


練習問題は以上となります。
章を重ねる毎に、問題のレベルも上がっていくのでしょうか?今回は組むのに時間がかかってしまいました。