7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

第7回 :: ruby_third

Last updated at Posted at 2020-12-02

!Mac OS X-10.15.7 !ruby-2.7.1p83$

if-elsif-else-end

お題

入力がうるう年(leap year)かどうかを表示するプログラムをかけ.

  1. うるう年は4で割り切れる数の年.ただし,
  2. 100で割り切れる年はうるう年でなく,
  3. 400で割り切れる年はうるう年.
  4. 2004, 1999, 1900, 2000で試せ.
  5. それぞれtrue, false, false, true

rubyのif

オブジェクト指向スクリプト言語 Ruby リファレンスマニュアル

上記のサイトには以下のように書かれている

if  [then]
   ...
[elsif  [then]
   ... ]
...
[else
   ... ]
end

上の表現で[]は省略可能箇所を示している.従って,最小で

if year%4==0 then
  p 'not leap year'
end

とかで書ける.さらにthenは省略可能で,ifをつなげるのはelsif.ややこしい.

類題:2004年はleap year

> ruby check_leap_2004.rb 2004

とした時に

true

と出力するプログラムを作る

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

上記のコードを実行すると

> ruby check_leap_2004.rb 2004
2004
true

となる.

類題:1999はfalse

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

上記のコードを実行すると

> ruby check_leap_0.rb 1999
1999
false

ちゃんと出力されてる.

類題:1900年と2000年は?

p year = ARGV[0].to_i
if yeay % 400 == 0
  p true
elsif year % 100 == 0
  p false
elsif year % 4 == 0
  p true
else
  p false
end

条件増やすだけ.

array, each

テストの自動化

この後,さらにテストの内容が増えてくると,いちいち引数(ARGV[0])で全てチェックするのが面倒.そこで,テストを自動化するために配列にテストする年を入れて,loopで回す.

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

類題:refactoring_methodに

さっき書いたコードをメソッド化する

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
[2004,1999,1900,2000].each do |year|
  p year
  leap?(year)
end

case

お題:case

さっきのコードをcaseを使って短くする

caseの文法

先ほどのオブジェクト指向スクリプト言語 Ruby リファレンスマニュアルにcaseの解説がある以下は文法

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

解法

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

上記のコードを実行すると

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

もっと短いのあった…

def leap?(year)
  case
  when year % 400 ==0 ; return true
  when year % 100 ==0 ; return false
  when year % 4 ==0 ;   return true
  else ;                 return false
  end
end

もっとすごいtdd

上の知識があると全く逆からのtddも可能.

def leap?(year)
  case 
  when year == 2000 ; p true
  when year == 1900 ; p false
  when year == 2004 ; p true
  else              ; p false
  end
end

より一般化して,

2000 -> % 400 == 0

とかにしても問題ない.

さらに,

def leap?(year)
  return case
	 when year % 400 ==0 ; true
	 when year % 100 ==0 ; false
	 when year % 4 ==0   ; true
	 else                ; false
	 end
end

とかもできる.

おまけ(三項演算子: ternary operator)

if_elseをもう少しスマートに書く方法があるらしい.

year = 1999
if year %4 ==0 then
  return true
else
  return false
end

return year%4 == 0 ? true : false
operation condition ? true_case : false_case

という文法でif-else-endを短く書くことが可能.

もう一つ,

return true if year %4 ==0

というようにelseがない場合は,ifを後ろに持っていくことが可能で,これも短くなる.unlessでも使えるらしい.実際に動かしてはない.

def leap?(year)
  return  (year%400 == 0) ? true :
    (year%100 == 0) ? false :
    (year%4 == 0) ? true : false
end

[2004, 1999, 1900, 2000].each do |year|
  p year
  p leap?(year)
end

と短くかけるんやって.


  • source ~/grad_members_20f/members/okamoto0910/article/c7.org
7
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?