[ プログラミング演習(Ruby) >  プログラミング演習(Ruby) 課題(2024) >  [課題07] 所要時間の計算 ]

[課題07] 所要時間の計算

課題

出発時刻と到着時刻を秒単位まで指定して,所要時間を何時間何分何秒という形で求めるプログラムを作成して提出してください.

この課題では,所要時間の計算に使われる出発時刻と到着時刻について,次のことを仮定します.

これらを満たさないデータが指定されたとしても,上の仮定のもとで処理してよいことにします.

課題ではメソッドを有効活用することを期待しています.

想定するプログラム実行例

プログラムのファイル名が仮に「elapsed_time.rb」であったとして, 想定される実行例を示します.


  $ ruby elapsed_time.rb
  出発時刻と到着時刻を指定して所要時間を計算します
  出発時刻(HH:MM:SS): 10:30:56 ⏎
  到着時刻(HH:MM:SS): 12:43:15 ⏎
  所要時間は2時間12分19秒です

  $ ruby elapsed_time.rb
  出発時刻と到着時刻を指定して所要時間を計算します
  出発時刻(HH:MM:SS): 8:11:3 ⏎ 
  到着時刻(HH:MM:SS): 22:05:18 ⏎
  所要時間は13時間54分15秒です

次に示すコードをプログラムの先頭にコピーして入れておくようにして下さい(必要事項は記入して下さい).


=begin

所属:     
氏名:     
学生番号:
難易度(5段階評価):

感想など(任意)

=end

[参考] ヘッダの調整

EmacsでRubyファイルを新規作成したときに取り込まれるヘッダは次のファイルに記述されています.

HOME > .emacs.d > template > template.rb

このファイルを編集して保存すれば,次回からは(新たにEmacsを起動すれば),変更後のヘッダが自動的に取り込まれるようになります.

なお「.」から始まる名前のファイル,フォルダ(ディレクトリ)は, 通常は見えないようになっています. Emacsで新規ファイルを作成する画面で「Show hidden files」にチェックを入れれば,「.」から始まる名前のファイルとディレクトリも表示されるようになります.

   Show hidden files 

プログラムの構成,サンプル

プログラム全体の構成は次のようになるでしょう.


  1. メソッド定義(1つ以上)

  2. メソッドを使った一連の処理
    2-1 データ入力
    2-2 計算
    2-3 結果の表示

次にサンプルプログラムを示します. ブラウザの画面で開いたときに文字化けしてしまう場合には, ダウンロードしてEmacs等で開いてみて下さい.

データ入力のための処理

次のように書くことで,端末ウインドウに質問文を表示しつつ, キーボードから文字列を読み取ることができます.


  # メッセージを端末のウインドウに表示して,キーボードから文字列を読み取る.
  # 読み取った文字列はstrに代入する.
  print "出発時刻(HH:MM:SS): "
  str = gets()

この例の場合,読み取った文字列は「変数str」に代入されます. 変数名は自由に決めて構いません.

getsで読み取られるデータは文字列(キーボードで入力された文字の並び)です. 「HH:MM:SS」の形式で時刻が指定されたとすると, 次のようにして文字列データから「時」「分」「秒」の数値(整数データ)を得ることができます.


   # サンプル時刻データ(10時30分56秒)
   str = "10:30:56"

   # strを':'で区切って,それぞれを整数に変換し(to_i),順にh,m,sに代入する
   h,m,s = str.split(':').map(&:to_i) 

   # h, m, sの値を使って時刻をputsで表示する  
   # 「10時30分56秒です」と表示される(最後に改行される)
   puts "#{h}時#{m}分#{s}秒です"  

この処理は,splitで指定した文字列(この場合は':')で数字が区切られていないと想定通りには動作しません.
splitに指定する文字列については空白の有無も区別されます. そこでたとえばsplit('  :  ')と書いた場合には, ':'ではなくて'  :  'によって区切ることになります. そのように指定した場合は'10  :  30  :  56'のように空白を入れないと期待通りには区切られません.

[参考] 数字列から数値への変換

数字列は飽くまでも文字の並びです.数値とは区別されます.


  x = '12'
  y = '34'
  z = x + y # z → '1234' (文字列同士の「+」は連結処理)

  a = x.to_i # xを整数に変換してaに代入
  b = y.to_i # yを整数に変換してbに代入
  c = a + b # c → 46

上に示した時刻データの入力では,文字列(HH:MM:SS)から切り出した数字列のそれぞれ(HH,MM,SS)を「to_i」で整数に変換しています.

「gets」でキーボードから取り込まれるのは常に文字列ですので,数値をデータとして取り込もうとする場合には注意が必要です. たとえば次のプログラムは動作しません.


  print('税抜き価格を入力してください:')
  s = gets()
  # 次の処理はエラーになる(文字列に「floor」は適用できない)
  y = (s * 1.10).floor # floorは小数点以下の切り捨て処理
  puts "税込価格は#{y}円です"

(価格として数字列が入力されるとして)期待通り動作させるには,次のように「to_i」によって数字列を数値(整数)に変換する必要があります.

  print('税抜き価格を入力してください:')
  s = gets()
  # OK(文字列sを整数に変換してから計算)
  y = (s.to_i * 1.10).floor # floorは小数点以下の切り捨て処理
  puts "税込価格は#{y}円です"

文字列への式の値の埋め込み

上でも示したとおり,文字列("...")中に「#{式}」と記述すると, 「式」を評価した結果に置き換えられます. 「式」は「数値」でなくても構いません.



  # キーボードから「名前」を読み込んで,「こんにちは」とあいさつする
  print "お名前を教えてください: "
  name = gets().chomp # chomp: 文字列の末尾に「改行」があれば,取り除く
  puts "こんにちは,#{name}さん!"

多重代入

Rubyでは,代入式の左辺に複数の変数,右辺に複数の式を指定して,それぞれの変数に対応する式の値を同時に代入できます. この仕組みを多重代入とよびます. 上に示した時刻の入力処理では,この多重代入を利用しています.


   # サンプル時刻データ(10時30分56秒)
   str = "10:30:56"

   # strを':'で区切って,それぞれを整数に変換
   # → 右辺の処理で整数が3つ得られて,多重代入によりh,m,sに順に代入される
   h,m,s = str.split(':').map(&:to_i) 

次に多重代入の具体例を示します.


  x,y = 1,5           # x = 1, y = 5
  a,b,c = x+y,x-y,x*y # a = 6, b = -4, c = 5

  z,w = 3,4           # z = 3, w = 4
  z,w = w,z           # zとwの値を交換(z=4,w=3になる)

ちなみに多重代入を使わない場合,上の例で示した2つの変数の値の交換はそれほど単純には実現できません. 次のようにしても値は正しく交換されません.


  z = 3
  w = 4

  # zとwの値を交換??(z=4,w=4になってしまう)
  z = w # この時点でz=4
  w = z # w=4となる

複数の値を返すメソッドの定義

Rubyでは複数の値を返すメソッドを定義できます. 次に2通りの例を示します.


  def powers(x)
    y = x**2   # x2
    z = x**3   # x3
    return y,z # yとzを返す(returnを使う方法)
  end

  def more_powers(x,k)
    y = x**k     # xk
    z = x**(k+1) # xk+1
    w = x**(k+2) # xk+2
    [y,z,w]      # y,z,wを返す(「配列」として返す方法)
  end
  
  u,v = powers(5) # ==> u == 25, v == 125
  a,b,c = more_powers(2,8) # ==> a == 256, b == 512, c == 1024

「配列」はデータを並べて構造化したデータです.この授業でも今後扱います.

Tips

以下,課題に取り組むにあたって,知っておくとよさそうなtips(hint)を示します.

[ プログラミング演習(Ruby) >  プログラミング演習(Ruby) 課題(2024) >  [課題07] 所要時間の計算 ]