今回は配列関係の練習問題。
(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 が取得できない際にエラーになってしまうようです。
練習問題は以上となります。
章を重ねる毎に、問題のレベルも上がっていくのでしょうか?今回は組むのに時間がかかってしまいました。