第7回(条件分岐)

# if-elsif-else-end

## お題はうるう年

    入力がうるう年(leap year)かどうかを表示するプログラムをかけ．
    1. うるう年は4で割り切れる数の年．ただし，
    2. 100で割り切れる年はうるう年でなく，
    3. 400で割り切れる年はうるう年．
    4. 2004, 1999, 1900, 2000で試せ．
    5. それぞれtrue, false, false, true

## 簡単な解説:if-elsif-else-end

```ruby
if 式 [then]
  式 ...
[elsif 式 [then]
  式 ... ]
...
[else
  式 ... ]
end
```

[]は省略可能箇所

## 詳しい解法:2004年はleap year

4で割り切れるので閏年

```ruby
p year = ARGV[0].to_i
if year % 4 == 0
  p true
end
```

受け取った引数を.to\_iで整数に変換し4で割り切れるときtrueを返す.

    > ruby check_leap_2004.rb 2004
    2004
    true

## 類題:1999はfalse

1999年は4で割り切れないので閏年ではない.

```ruby
p year = ARGV[0].to_i
if year % 4 == 0
  p true
else
  p false
end
```

結果

    > ruby check_leap_0.rb 1999
    1999
    false

# array, each

## お題:テストの自動化

テストの内容が増えたときいちいち引数でチェックするのが面倒なので自動化

## 簡単な解説: array, each

```ruby
各要素に対してブロックを評価します。

ブロックが与えられなかった場合は、自身と each から生成した
Enumerator オブジェクトを返します。

[1, 2, 3].each do |i|
puts i
end
#=> 1
2
3
```

この記法では，出力が#=>以下に記される.

配列Arrayは[]で定義.do-loop内で使う値は'|i|'のように縦棒で挟まれた変数名に入る.

## array,eachを用いたテスト自動化

```ruby
[2004, 1999].each do |year|
  p year
  if year%4 == 0
    p true
  else
    p false
  end
end
```

結果

    > ruby check_leap_2004_1999.rb
    2004
    true
    1999
    false

## 詳しい解法1:1900はtrue? いえいえfalse

1900は4で割り切れるが,100で割り切れるので閏年ではない.1900でfalseが返るよう変更.

まずはテストの修正

```ruby
[1900, 2004, 1999].each do |year|
```

次に100で割り切れる場合の処理

```ruby
if year % 100 == 0
  p false
end
```

とりあえず付け加えてみる

```ruby
[1900, 2004, 1999].each do |year|
    p year
    if year %  100 == 0
      p false
    end
    if year % 4 == 0
      p true
    else
      p false
    end
  end
```

結果

    > ruby check_leap_1900_2004_1999.rb 
    1900
    false
    true
    2004
    true
    1999
    false

1900が100で割り切れるかどうか判断したあとそのまま4で割り切れるか判断されて結果falseのあとtrueが出力される.なので条件を満たしたら次の要素に移るnextを追加

```ruby
[1900, 2004, 1999].each do |year|
    p year
    if year %  100 == 0
      p false
      next
    end
    if year % 4 == 0
      p true
    else
      p false
    end
  end
```

結果

    > ruby check_leap_1900_2004_1999.rb 
    1900
    false
    2004
    true
    1999
    false

これでOK

## 詳しい解法2:refactoring 条件式の単純化

先ほどの条件式は二つに完全に分けているがもっと単純にできる.

```ruby
[1900,2004,1999].each do |year|
  p year
  if year % 100 ==0
    p false
  else
    if year % 4 == 0
      p true
    else
      p false
    end
  end
end
```

elsifで更に単純に

```ruby
[1900,2004,1999].each do |year|
  p year
  if year % 100 ==0
    p false
  elsif year % 4 == 0
    p true
  else
    p false
  end
end
```

## 類題:そして2000はtrue！

2000は400で割り切れるので閏年

```ruby
[2000, 1900, 2004, 1999].each do |year|
  p year
  if year % 400 == 0
    p true
  elsif year % 100 == 0
    p false
  elsif year % 4 == 0
    p true
  else
    p false
  end
end
```

結果

    > ruby check_leap_2000_1900_2004_1999.rb 
    2000
    true
    1900
    false
    2004
    true
    1999
    false

## 類題:refactoring\_methodに

今書いたものをメソッドに

```ruby
def leap?(year)
  if year % 400 == 0
    p true
  elsif year % 100 == 0
    p false
  elsif year % 4 == 0
    p true
  else
    p false
  end
end
[2000, 1900, 2004, 1999].each do |year|
  p year
  leap?(year)
 end
```

# case

## 簡単な解説

```ruby
case [式]
[when 式 [, 式] ...[, `*' 式] [then]
  式..]..
[when `*' 式 [then]
  式..]..
[else
  式..]
end
```

## 解法

```ruby
def leap?(year)
  case
    when year % 400 == 0 ; p true
    when year % 100 == 0 ; p false
    when year % 4 == 0 ; p true
    else ; p false
  end
end
[2000, 1900, 2004, 1999].each do |year|
  p year
  leap?(year)
end
```

結果

    > ruby check_leap_2000_1900_2004_1999.rb 
    2000
    true
    1900
    false
    2004
    true
    1999
    false

問題にもよるけどcaseのほうが見やすそう.

------
 - **source** ~/grad_members_20f/members/yoshida/c3_if_case_leap_year.org