Ruby silver試験対策メモ

追記

無事合格しました！よかったー。スコアは84点でした。

受けてみての感想は、
- 本と過去問やって、間違わないようになってれば大体大丈夫
- メソッドの細かい部分に突っ込まれることはあまりない
- sortからの出題が意外に多かったので注意
- 慌てずに最後ちゃんと、じっくり見直すこと
    - 意外とこれで救えたのがあった

以上です。

-------


会社でRuby silver/gold をとりましょう！と言われたので勉強中。とりあえず雑多にログを残していきたいと思います。随時更新、気が向けば整理していくかも。

**参考**
https://rex.libertyfish.co.jp/
https://www.amazon.co.jp//dp/4774191949/
http://www.minituku.net/drills/

https://gist.github.com/kwatch/2814940
https://qiita.com/naoty_k/items/f84b2a9034a3bb3bfcb2
https://qiita.com/tsuruokax/items/db936ff7312ba7d97315


判定式の問題は特に注意して必ず最後に見直したほうがいいな

# 例題集
#### 初期化してない
```ruby
x = 0 
def hoge
  (1...5). each do | i |
  x += 1 
  end
  puts x 
end
hoge
# => 例外発生。x += 1の前に初期化してないから
```

#### 例外の順番
```ruby
begin 
  puts 1 +" 2" 
rescue 
  puts "Error." 
rescue TypeError 
  puts "Type Error." 
ensure 
  puts "Ensure." 
end
# => 'Error.', 'Ensure' 先に拾ってるのでTypeErrorは出ない
```

#### ひっかけ問題 (型
```ruby
def foo(*a)
  p a
end
foo 1,2,3
# => [1,2,3] が正解。選択肢に["1","2","3"]とかあるので選ばないように気を付ける
```

#### ひっかけ問題 (破壊、非破壊
```ruby
s1 ="Hoge" 
s2 ="Fuga" 
s1.concat(s2) 
s1.chop 
s1.chomp 
s1 + s2 
puts s1
# => "HogeFuga" concat以外は非破壊、s1+s2は代入していない。
```

#### ひっかけ(?)問題 (判定 
```ruby
y = false
y __(1)__ ( raise "failed") 
puts("succeeded!")
=> "succeeded!"
```
と、するために__(1)__に入るものは？ 正解は `&&` 。
左がfalseの場合右を評価しないため。


#### ひっかけ(?)問題 (クラス 
```ruby
class Hoge < Object ; end
class Hoge < Kernel ; end # => error Kernelはモジュールなので継承できない
```

#### Arrayの変換
```ruby
a = 1,2,3 # => [1,2,3]
a.to_s  # => "[1,2,3]"
a.join(",") => "1,2,3"
```

#### ひっかけ(?)問題 (判定 
```ruby
a = [1,2,3,4]
b = [1,3,5,7]
a || b    # => [1,2,3,4]
a | b     # => [1,2,3,4,5,7]
```
# Time関連
|書式|	簡単な説明|	記述例|	出力例|
|---|---|---|---|
|%Y	|西暦	|"%Y"|	2018|
|%y	|西暦(下2桁)	|"%y"|	18|
|%m	|月(2桁)	|"%m"|	01|
|%d	|日(2桁)	|"%d"|	02|
|%-d|	日(1~2桁)	|"%-d|	2|
|%e	|日(空白埋め2桁)	|"%e"|	△2|
|%H	|時(2桁)24時間制	|"%H”|	03|
|%-H|	時(1~2桁)24時間制	|"%-H|	3|
|%k	|時(空白埋め2桁)24時間制	|"%k”|	△3|
|%l	|時(1~2桁)12時間制	|"%l”|	△3|
|%M	|分(2桁)	|"%M”|	04|
|%-M|	分(1~2桁)	|"%-M|	4|
|%S	|秒(2桁)	|"%S”|	05|
|%-S|	秒(1~2桁)	|"%-S|	5|
|％L	|ミリ秒	|"%L”|	567|
|%F	|日付	|"%F”|	2018-01-02|
|%T	|時刻(時分秒)24時間制	|"%T”|	03:04:05|
|%R	|時刻(時分)24時間制	|"%R”|	03:04|
|%r	|時刻(時分秒)12時間制と午前または午後|"%r”|03:04:05 AM|
|%P	|午前または午後(小文字)	|"%P”|	am|
|%p	|午前または午後(大文字)	|"%p”|	AM|

```ruby
puts Time.now.strftime("%y-%m-%d %-H:%-M:%-S %r")
# => 19-11-11 12-12-12 AM  #みたいな感じ
```



# Hash関連

## よくあるやつ
-  revertは存在しない
  - invertはある。キーと値を逆にするメソッド。(revertはRailsのメソッド)

- containは存在しない
  - **hashに限らずcontainというメソッドは存在しないっぽい**

- merge, merge!
  - mergeは非破壊メソッド。二つのハッシュをまとめて一つにする。キーが重複した場合は引数にしたほうのハッシュが優先される。

#### アスタリスクがついてると変数が配列として展開される。
```ruby
hash = {a: 100, b: 200}

def splat_hash(a, b)
  p a
  p b
end

splat_hash(*hash)
=> これは[[a: 100], [b: 200]]で受け取られる

```

#### 初期化
```ruby
a = Hash.new
a = Hash.new(1) # 引数を渡すとこれがデフォルト値になる。キーがないときは常にこれが返る

a = Hash({}) #これも可能
a = Hash()  # これはエラー
a = Hash[]  # これは可能と思ったら、ver2.1ではできないらし
い。。。

p hash1 = { "key1" => "value1", "key2" => "value2" }
# {"key1"=>"value1", "key2"=>"value2"}

p hash2 = { :key1 => "value1", :key2 => "value2" } 
# {:key1=>"value1", :key2=>"value2"}

p hash3 = Hash[:key1, "value1", :key2, "value2"] 
# {:key1=>"value1", :key2=>"value2"}

p hash4 = Hash[1, "value1", 2, "value2"] 
# {1=>"value1", 2=>"value2"}

p hash5 = { key1: 1, key2: 2}
# {:key1=>1, :key2=>2}

# Arryからto_hash
p hash = [["a",1]].to_h # 要素が一つでも二次元になってないとエラーになる点に注意。
# => {"a" => 1}
```

#### ちょいひっかけ
```ruby
a = {"Foo" => "Hoge", "Bar" => "Piyo", "Baz" => "Fuga"} 
b = {"Foo" => "hoge", "Bar" => "piyo", "Baz" => "fuga"} 
p a. update(b).sort{|a, b| a[1] <=> b[1] }
# =>[[" Baz", "fuga"], ["Foo", "hoge"], ["Bar", "piyo"]]
```

#### ハッシュの中身はArray
```ruby
h = {a: 100, b: 200}
h.each {|nakami|
    p nakami
    # => [:a 100] , [:b 100]
    p nakami.class 
    # => Array 
}
```

## 例題
#### 以下のコードを実行して文字列sの単語毎の出現回数を出力させたい。(1),__(2)__に入る最適な組み合わせを１つ選択してください。

```ruby
s = "To be or not to be, that is the question."
hash = Hash.new(0)
s.__(1)__(__(2)__) {|i| hash[i] += 1}
p hash["be"] #=>2
```
A. (1)match (2)/\w+/
B. (1)sub (2)/\w+/
C. (1)scan (2)/\w+/
D. (1)search	(2)/\w+/
正解は**C**
wは英数字, +は連続を表すので、この場合は空白でsplitしているような感じ。matchは最初の一つしかこないけどscanは全部来る


# 例外処理

## 基本の書き方
```ruby
# raise 例外の定数,'エラーメッセージ' が本来の書式 
raise ArgumentError,'Error Message' # これは正しい
raise ['Error Message']  # これはNG (引数がarrayになっている)

raise # これでも例外を発生させることが可能OK

# 例外処理の基本的な書式
begin
  raise
  rescue
    p "例外です"
    p $!  # これでスタックトレースを表示できる。$!は例外を自動で拾ってくれてる特殊変数。

  ensure
    # javaで言うfinally
end

begin
  # 処理
  rescue => e   # ->これは使えない。lambdaの書き方なので。
    p e  # こういうスタックトレースの出し方もある
end
```

```ruby
begin
  raise StandardError.new # ここに何も書かない場合はRuntimeErrorになる
rescue => e
  puts e.class  # => StandardError
end
```
こちらもよく読んでおくとよろしい
- https://qiita.com/kasei-san/items/75ad2bb384fdb7e05941


# 文字列関連
- swapcase, swapcase!は大文字小文字を逆転
- capitalize, capitalize! は先頭大文字に
- delete, delete! は任意文字削除
(上記のメソッドは破壊、非破壊に注意)
- succ,nextは同じ。次の文字を返す(a.succ => b)
- concatは!が付かない破壊的メソッド
- upcase, upcase! 両方あるのでひっかからないように
- `"A".ord =>65` `65.chr`の逆をやるメソッド

#### []は範囲で置き換えられる
```ruby
a= "a123456"
a[1,3] = "x"
p a 
# => "ax456" 
```



#### casecmpは大文字小文字を区別しない比較演算子 (<=>と同じ) なので、自分のほうが前の文字なら-1, 後の文字なら1, 同じなら0が返る
```ruby
p "a".casecmp("b")
# => -1
p "b".casecmp("a")
# => 1
p "b".casecmp("b")
# => 0
```  

#### Stringにbinaryというメソッドは無い
`"7".binary` これはエラー

#### chompは引数で区切り文字を指定できる
```ruby
s = "hello:"
p s.chomp(":")
# => "hello"
```


#### **は*よりも優先度が高い

```ruby
 p "foo" * 2 **2
 => "foofoofoofoo"
```

#### "0-5"みたいな書き方は範囲指定になるそうです
```ruby
puts "0123456789".delete("0-58-")
=> 679
```

#### sliceとslice!は挙動が違う(俺的に)
```ruby
str = "string"

#sliceは切り取った文字列が返ってくる
str.slice(1,2)
=> "tr"

#slice!はレシーバーから文字を切り取る
str.slice!(1,2)
p str
=> "sing"
```

## 例題
#### 以下のコードを実行した出力として正しいものを１つ選択してください。
```ruby
puts "Ruby on Rails".delete("Rails")
```
A.エラーが発生
B.Ruby on
C.Rails
D.uby on
E.Ruby
**正解:D**
例えば、String.delete('args')とした場合、a,r,g,sが消される（'args'が消されるのではない）

#### 以下のコードを実行したときの出力として適切な物を1つ選択してください。
`str = "RubyAssociation\r\n".chop`
A."RubyAssociation"
B."RubyAssociation\r"
C."RubyAssociation\r\n"
D."RubyAssociation\r\n\r\n"

**正解:A**
chopは末尾一文字を消去するメソッドだが、\r\nが来たときだけはこれを一文字とみなして\r\nを消すそうだ。

#### 以下のコードを実行したときの出力として適切な物を1つ選択してください。
```ruby
string = "test code"
string.slice(0,4)
p string
```
A."test"
B."test code"
C.nil
D.""

**正解:B**
Aを選んでしまったが、slice!ではないので、この場合Bが正しい。見落とさないように気をつけねば。。

# 判定式

#### 同一性の判定
```ruby
a = 2
b = 2.0

p a == b      # => true
p a === b     # => true
p a.eql? b    # => false
p a.equal? b  # => false
# 上から、同値性, 所属性, 型同一性, 同一性を比較している 
```



# クラス、モジュール、スコープ

#### require
- requireするとファイルが評価される
    - 読み込んだものがclassの場合、そのまんま使える
    - 読み込んだものがmoduleの場合、includeしないと使えない
 
#### extend (モジュール)
- extend Module_name とすると、特異クラスにモジュールのメソッドが追加される


#### ::で始まるとそれはトップレベルのスコープを指す。

```ruby
Foo = "main"
 
class Bar
  Foo = "foo"
 
  def self.foo
    ::Foo
  end
end
 
p Bar.foo
=> "main"  # "foo"を出したかったら::を消すべき
```

####  以下の出力になる時の___(1)___に入るものとして適切なものを1つ選択してください。
```ruby
class Foo
  ___(1)___= 0
  def self.count
    ___(1)___ += 1
  end
end

class Bar < Foo
end

puts Foo.count
puts Bar.count
```
[出力]
1
2
A.`num`
B.`@num`
C.`@@num`
**正解:C**
`@num`だとインスタンス変数になってしまうので、newしてインスタンスを起こさないとこういう風には使えない。
`@@num`は **クラス変数** というものなので、newしなくても使える。全クラスで同じ値が使われる。


# File関連
- File.fileno, fileno= はgetsされた回数を記録しているものであり、seekするものではない。つまり、値を代入してもファイル内の読んでる位置が変わるわけではない。ややこしいな。

- statとかmtimeとか見ておいたほうが良さげ
    - atime : アクセス日時
    - mtime : 更新日時（中身を変える
    - ctime : 状態変更日時 更新だけでなくchmodとか

- **モードの引数は文字列になってないとだめ**

- w, w+, a, a+, r, r+それぞれの挙動の違いを理解しておかないとだめ。
  - 先にファイルが存在するか？で挙動が変わったり、どこからファイルを更新していくのか？などなど。

|記号| モード |
|--- | --- |  
|r	|読み込みモード |
|r+	|読み込み + 書き込みモード |
|w	|新規作成・書き込みモード |
|w+	|新規作成・読み込み + 書き込みモード |
|a	|追記書き込みモード |
|a+	|読み込み + 追記書き込みモード  |
  
#### basename
```ruby
["bin/hallo.py", "ola.lua", "/tmp/hej.cpp"].each do |filename|
  # 第2引数で ".*" を入れておかないと拡張子がそのまま出力される点に要注意
  puts File.basename(filename, '.*') + '.rb'
end
#=> hallo.rb
#=> ola.rb
#=> hej.rb
```


#### File.openしたときにモードを指定しないときはrで開かれる。ので、その場合puts, writeはできない。
```ruby
FIle.open("/path/to/link", "a") do |f|  #これはおｋ
FIle.open("/path/to/link", a) do |f|  #これはNG
FIle.open("/path/to/link", a+) do |f|  #これはNG
```

#### putsは配列を渡すと自動的に改行してくれるらしい

```ruby
File.open("test.txt", "w") do |f|
  f.puts(["a","b","c"])
end
# ファイルには
#a
#b
#c
# って入る
```

#### 以下のコードを実行したときの出力として適切な物を1つ選択してください。
`p File.join("ruby", "exam","silver")`
A."./ruby"
B."./ruby/exam/silver"
C."rubyexamsilver"
D."ruby/exam/silver"

**正解:D**
File.joinはスラッシュでつないでくれる。引数は可変長なのでたくさん来ても大丈夫。

#### テキストファイルを読み込んだファイルオブジェクトから一行ずつ読み込み表示したい。目的に一致するIOクラスのメソッドを２つ選択してください。
A.readlines
B.read
C.gets
D.readline
E.find
**正解:C, D**
下記は参考コード

```ruby
File.open("data.txt", "r") do |io|
  puts "---gets"
  p io.gets      #１行読み込んで表示

  puts "---readline"
  p io.readline  #１行読み込んで表示

  puts "---read"
  io.rewind      #読み込み位置を先頭に戻す
  p io.read(5)   #5バイト分読み込んで表示
  p io.read      #現在位置よりファイル全体を読み込んで表示

  puts "---readlines"
  io.rewind      #読み込み位置を先頭に戻す
  p io.readlines #ファイルの各行を要素とする配列を作成して表示
end
```

#### 次のメソッドでDirクラスのクラスメソッドではないものをすべて選択してください。(2つ選択)
A.Dir.rmdir
B.Dir.basename
C.Dir.pwd
D.Dir.extname
E.Dir.getwd  
**正解:B, D**  
basename, extnameはFileクラスのメソッド（ちなみにgetwd, pwdのwdはworking directory)

# 正規表現
#### 早見表
|用途 | 正規表現|
|---|---|
|1文字を表現 | ドット(.)|
|0回以上繰り返し | アスタリスク(*)|
|直前の文字を1回以上繰り返し | プラス(+)|
|直前の文字を0回か1回出現 | クエスチョンマーク(?)|
|範囲で指定した回数繰り返し | 範囲指定（{min, max}）|
|いずれかの1文字にマッチ | ブラケット（[]）|
|範囲を表現する | ハイフン（-）|
|単語構成文字 | \w|
|非単語構成文字 | \W|
|空白文字 | \s|
|非空白文字 | \S|
|10進数字 | \d|
|非10進数字 | \D|
|16進数字 | \h|
|非16進数字 | \H|
|繰り返しマッチ | かっこ()|
|先頭にマッチ | キャレット（^）|
|先頭にマッチ | バックスラッシュA（\A）|
|文末にマッチ | ダラーマーク（$）|
|文末にマッチ | バックスラッシュz,Z（\z, \Z）|
|エスケープ | バックスラッシュ（\）|

#### ^ キャレットに要注意
`[^x]` この場合はxという文字以外にマッチという否定の意味になる.
`^[x]` この場合は先頭がxという文字にマッチという前方一致の意味になる。
ブラケットの中か外かで扱いが変わるので要注意。

ex)
```ruby
puts "0123456789-".delete("^13-56-")
# => "13456-"   #指定以外にマッチしdeleteしている
```



## 例題
#### 以下,(A)に入る正しい文字列は？
```ruby
p /[^P|p]rogramming/ =~ (A)
```
=> Arogramming など
^はnotを意味する。[]は部分一致、|はORなので。


# その他
- グローバル変数は必ず$で始まる
- インスタンス変数は@
- クラス変数は@@
- 定数はアルファベット大文字 (再代入可能。ただし警告が出る)

#### 再定義できない演算子(自己代入演算子)

` =  ?:  ..  ...  not  &&  and  ||  or  ::`

#### and,&&演算子の動き(リファレンスからそのまま引用

```ruby
# 左辺を評価し、結果が偽であった場合はその値(つまり nil か false) を返します。
# 左辺の評価結果が真であった場合には 右辺を評価しその結果を返します。
# and は同じ働きをする優先順位の低い演算子です。

p(nil && false) # => nil
p(false && nil) # => false
p(1 && 2) # => 2

# ここは自分で追記
a = [1,2,3,4] ; b=[1,3,5,7]
a && b
# => [1,3,5,7]  # 左がtrueなので右の値が返ってくる

# and を伴う式をメソッドの引数に渡す場合は二重に括弧が必要となります。
p(true && false)    #=> false
p((true and false)) #=> false
```


#### ローカル変数の名前として正しいものをすべて選択してください。
A._365
B.z
C.7years
D.break
E.latitude
**正解：A,B,E**
アンダーバーで始まるときに仕様上の縛りはない。（慣習としてメソッドが書かれることが多いというだけ)

#### 組み込みライブラリ、Integer#chr（encoding)についての説明として正しいものはどれか、2つ選択してください。
A.引数を指定しなかった場合はエラーが発生する。
B.指定されたエンコーディングでselfを正しく解釈できない場合はnilが返される。
C.引数で与えられたencodingにおいて、selfを文字コードと見なし、それに対応する一文字からなる文字列を返す。
D.指定されたエンコーディングでselfを正しく解釈できない場合はエラーが発生する。
**正解:C,D**
全く知らなかったが、こういうコードの話。

```ruby
p 65.chr # "A"
x = 25991
p 25991.chr(Encoding::UTF_8) # "文"
```

#### 以下のコードを実行したときの出力として適切な物を1つ選択してください。
```ruby
ary = []
ary << 1 && false
true || ary << 2
false && ary << 3
false || ary << 4
p ary
```
A. [1, 4]
B. [1, 2, 3, 4]
C. [1]
D. [1, 2, 3]
**正解:A**
最初うっかりBを選んでしまった。**式がORの場合は、左辺がtrueであれば右辺は実行されない**点に注意。true=実行という先入観が働いてしまいがち。


#### 以下のコードを実行したときの出力として適切な物を1つ選択してください。

```ruby
class Object
  def greeting
    print "How are you?\n"
   end
end
[1,2].greeting
```

A.エラーが発生
B.nilが表示される
C.How are you?
D.[1,2]
**正解:C**
末尾の行に追加して`p [1,2].class.ancestors`をすると、Objectクラスを継承しているのがわかる。つまりこのgreetingメソッドは普通に使える。

#### Timeは基本的に秒で計算
以下は60分後が正解

```ruby
puts Time.now + 3600
```

#### 予約語
```ruby
# LINE
alias
class
elsif
if
not
return
undef
yield

# ENCODING
and
def
end
in
or
self
unless

# FILE
begin
defined?
ensure
module
redo
super
until

# BEGIN
break
do
false
next
rescure
then
when

# END
case
else
for
nil
retry
true
while

```



#### 組み込み定数
```ruby
STDIN
STDOUT
STDERR
ENV
ARGF
ARGV
DATA
TOPLEVEL_BINDING
RUBY_VERSION
RUBY_RELEASE_DATE
RUBY_PLATFORM
RUBY_PATCHLEVEL
TRUE (obsolete)
FALSE (obsolete)
NIL (obsolete)
VERSION (obsolete)
RELEASE_DATE (obsolete)
PLATFORM (obsolete)
# ※(obsolete)は現在非推奨となっているものです。
```




# Array関連

#### よくあるやつ
- delete_ifとreject! はほぼ同じ。ブロックの評価値が真なら引数をレシーバから削除。rejectは削除しなかった場合何も返さない点がちょっとちがう。
- each_sliceとeach_cons
- `[1,2,3]flatten!  # => nil`
- **slice, shift, pop, find_all(=select), map(=collect)** あたり要チェック。
- shift, popは破壊メソッドのみ(shift!は存在しない！）
- mapは破壊、非破壊両方ある。


#### いろいろひっかけ
```ruby
a = [:a,:a,:b,:c] 
a[5]= :e  # => indexが5なので間にnilが入る 
a.concat([:a,:b,:c]) 
a.compact # compactはnil消去。だけどこれは!無いので非破壊
a.uniq    # compactは重複消去。だけどこれは!無いので非破壊
p a
# => [:a, :a, :b, :c, nil, :e, :a, :b, :c]
```


#### 先頭同士の組み合わせがzip, 総組み合わせがproduct

```ruby
arr = [1,2].zip([3,4])
=> [[1, 3], [2, 4]]

[1,2].product([3,4])
=> [[1, 2], [1, 4], [2, 3], [2, 4]]
```

#### map_with_indexの引数はオフセット。injectのそれとは違うよ。
```ruby
(10..12).to_a.map.with_index(1) do |elem, i|
  puts i
end
=> 1  # 引数に何も入れないとこれは０になる
2
3
```

#### unshiftは引数を取らない場合は何も操作しない
```ruby
s = ["one", "two", "three"]
s.shift
s.shift
s.unshift
s.push "four"
p s

# <実行結果>
#  ["one", "two", "three"]
#  ["two", "three"]
#  ["three"]
#  ["three"]
#  ["three", "four"]
```
#### at, fetch, values_atの違い
```ruby
nums = [1,2,3,4,5]
# atとfetchは同じ。単一の引数しか取れない
nums.at(2) # => 3
nums.fetch(2) # => 3

# values_atは配列で戻ってくる。範囲指定も可能
nums.values_at(2) # => [3]
nums.values_at(2..3) # => [3,4]
```



#### 以下はエラーにならない。pが先に評価されるだけ。

```ruby
p [1,2,3,4].map do |e| e * e end
=> #<Enumerator: [1, 2, 3, 4]:map>
```

#### Any?の挙動
ブロックを実行し、戻りがtrueになった時点で**繰り返しを止める**。

```ruby
$val = 0

class Count
  def self.up
    $val = $val + 1
    $val == 3 ? true : false
  end
end

[*1..10].any? do
  Count.up
end

p $val  # => 3
```

#### Enumerable.injectの挙動
以下のコードの実行後の状態を選択肢から選べ、みたいな問題。

```ruby
p [1, 2, 3].inject{|x, y| x + y ** 2} rescue p $!
p [1, 2, 3].inject(0){|x, y| x + y ** 2} rescue p $!
p [1, 2, 3].inject([]){|x, y| x << y ** 2} rescue p $!
p [1, 2, 3].inject do|x, y| x + y ** 2 end rescue p $!
```

上から順番に解説

```ruby
# 元の式を変数が見えるようにちょっと修正
count = 0
p [1, 2, 3].inject{ |x, y|
    count += 1
    puts "count: " + count.to_s
    puts "x: " + x.to_s
    puts "y: " + y.to_s
    x + y ** 2
} rescue p $!

# 実行結果
# count: 1
# x: 1
# y: 2
# count: 2
# x: 5
# y: 3
# 14
```

injectは実行されたブロックの戻り値が次の引数になる（初回は引数の
値）。なので、
1回目 x:1, y:2  ret=5
2回目 x:5, y:3  ret=14
ここまでで引数の終端に来たのでブロックを抜ける。
結果は14。

次のやつも同様に変数を見えるように修正して実行してみる。
最初の引数が0になっていることがわかるが、計算の結果は前回同様14。

```ruby
count = 0
p [1, 2, 3].inject(1){|x, y| 
    count += 1
    puts "count: " + count.to_s
    puts "x: " + x.to_s
    puts "y: " + y.to_s
    x + y ** 2
} rescue p $!

# 実行結果
# count: 1
# x: 0
# y: 1
# count: 2
# x: 1
# y: 2
# count: 3
# x: 5
# y: 3
# 14
```
  

3つ目の配列の場合も、同様に修正して実行すると中身がよくわかる。

```ruby
count = 0
p [1, 2, 3].inject([]){|x, y| 
    count += 1
    puts "count: " + count.to_s
    puts "x: " + x.to_s
    puts "y: " + y.to_s

    ret = x << y ** 2
    puts "ret: " + ret.to_s
    ret
} rescue p $!

# 実行結果
# count: 1
# x: []
# y: 1
# ret: [1]
# count: 2
# x: [1]
# y: 2
# ret: [1, 4]
# count: 3
# x: [1, 4]
# y: 3
# ret: [1, 4, 9]
# [1, 4, 9]
```

最後のやつはinjectにブロックが渡されない（先にpが実行される)のでエラーになる。

```ruby
p [1, 2, 3].inject do|x, y| x + y ** 2 end rescue p $!
#=> #<LocalJumpError: no block given>
```

↑と似たような例

```ruby
p [1,2,3,4].map do |e| e * e end #これだと do endブロックは渡されない
# #<Enumerator: [1, 2, 3, 4]:map>

p [1,2,3,4].map{ |e| e * e }     #こっちが正しい
# [1, 4, 9, 16]
```

#### product, transpose
```ruby
arr = [1,2].product([3,4]).transpose
p arr
# -> [[1, 1, 2, 2], [3, 4, 4, 4]]

# productで[[1,3],[1,4],[2,3],[2,4]] ができた後、
# transposeで行と列が入れ替わる。

# transpose前
# [ [1,3],
#   [1,4],
#   [2,3],
#   [2,4]  ]

# transpose後
# [ [1,1,2,2],
#   [3,4,3,4]  ]
```

#### each_consの挙動
```ruby
arr = (1..30).to_a
container = []

arr.each_cons(7) do |i|
  container << i
end
p container.length
# -> 24

# 要するに array.each_cons(arg){|block| 処理 } とすると、
# arrayからarg数だけ取り出した配列をblockとして、処理が実行される。
# この場合なら[1,2,...7],[2,3,...8],,,,[24,25,...30]まで行くと終了
```

#### each_sliceの挙動
```ruby
arr = (1..30).to_a
container = []

arr.each_slice(7) do |i|
  container << i
end
p container.length
# -> 5
# こっちはeach_consと違って、7個ずつ連続で取り出す
# [[1,2,..7][8,9,..14],..,[22,23,...28],[29,30]] でlengthは5
```

## 例題
#### 以下のコードを実行した時の出力に対して__（１）__に入る適切な記述を２つ選択してください。
```ruby
p [1,1,2,3,5,8].__(1)__｛|x| x*2}
# => [2,2,4,6,10,16]
```
A.compact
B.collect
C.map
D.flatten
E.join
**正解：B,C**
mapとcollectは同じ処理。「二つ」と書いてあるのを見落とさないように。


#### 以下の__(1)__に入る適切な記述を2つ選択してください。
```ruby
a = [1,2,3,4,5]
p __(1)__
# => [1,2,3]
```

A.a[0..2]
B.a[1..2]
C.a.slice(0,3)
D.a.slice(0...2)
**正解:A,C**
これも慌ててAを選び忘れた。要注意。。。


#### 下のコードを実行した時の出力に対して__(1),(2)__に入る最適な組み合わせを１つ選択してください。
```ruby
p "100,200,300,400,500".___(1)___.___(2)___
[出力]
"100\n200\n300\n400\n500"
```
A.(1)split(",") (2)join("\n")
B.(1)to_a(",") (2)join("\n")
C.(1)split(",") (2)concat("\n")
D.(1)concat(",") (2)join("\n")
**正解:A**
慌ててBを選んでしまったが正解はA。配列に変換するのはto_aだけではない（というかこれはto_aで配列に変換はできない)。冷静に問題文を読むこと。。。。


#### 以下のコードを実行した時の正しい出力結果を1つ選択してください。
```ruby
numbers = (1..20).to_a
p numbers.detect{|x| x % 5 == 0}
```
A.nil
B.10
C.5
D.20
E.[5,10,15]
**正解:C**
numbers(rangeオブジェクト)をdetectが引数にしてるブロックで評価して最初に真になった値が返る。findでも同じ結果になる。find_allだと[5,10,15,20]が返る。