プログラミング学習

Rubyやrailsについて学んだことをアウトプットしています。

【Paizaラーニング】RubyのC問題を攻略する

私は現在PaizaアプリでRuby言語を勉強しており、Bランクを目指しています。

今回はCランクレベルアップ問題集の「文字列FINAL問題」を解いていきます!




問題について

パイザ君の家の前では毎週日曜日に工事が行われます。この先 N 週間、工事が日曜日の何時に始まり、どれくらいの時間続くのかは分かっています。パイザ君は工事の間は家を離れようと思っているので、それぞれの日に工事が何時に終わるのかを知りたいと思いました。
工事が N 週間続くとして、各週日曜日の工事が始まる時刻と、工事が何時間何分続くのかに関する情報が与えられるので、工事が終わる時刻を 00:00 から 23:59 までの 24 時間表記で出力してください(ここで「工事が終わる時刻」とは、工事が h 時間 m 分続くとした場合、工事が始まった時刻の h 時間 m 分後を指します)。

上記が今回の問題文になります。 入力・出力例としては

1
13:00 1 30

が入力されると

14:30

が出力されます。現在時間(13:00)と工事にかかる時間(1:30)が入力されて工事終了後の時刻が表示されていることがわかりますね。
それでは次にコードを書くために問題文をかみ砕いていきましょう。

回答のポイント

この問題で重要となる点は以下の3点です。

  • 入力された値の受け取り方

  • 時間の繰り上げについて

  • 出力時に00:00のにすること

それぞれ見ていきましょう。

まず、入力された値の受け取り方について今回受け取る数値は以下のように分けられます。

  • n…工事が何週間続くのかを表す。

  • h…現在時刻の時間部分を表す。

  • m…現在時刻の分部分を表す。

  • h_a…追加される時間数を表す。

  • m_a…追加される分数を表す。 これらを踏まえて入力された値を受け取るコードを書いてみましょう。

n = gets.to_i
# 工事が続く回数だけ終了時刻を求めるのでn以下の値はeachメソッドを使用して繰り返し処理を行います。
n.times do
    h_m, h_a, m_a = gets.split(" ")
# ここではsplitメソッドを使用し、入力された値をスペース区切りで配列に格納します。
# 配列の長さと同じ変数を並べて代入すると配列の要素が先頭からそれぞれの変数に代入されます。
    h, m = h_m.split(":").map(&:to_i)
# h_mには現在時刻が13:46といった形で入っているのでそれぞれ時間と分数に分けてあげます。
# mapメソッドを使用すると配列の各要素に指定したメソッドの処理を受け取ることができます。今回は文字列で受け取った入力値を数値へと変換しています。
    h_a = h_a.to_i
    m_a = m_a.to_i
# ここでも同様に文字列の値を数値に変換しています。それぞれの値を数値に変換しないと足し算が行えないからです。
end

次に受け取った時刻に工事の終了時刻を追加してあげましょう。

h_t = h + h_a
m_t = m + m_a

これでh_tが終了時刻をm_tが終了時刻の分数を表すようになりました。

次に時間の繰り上げについて考えていきます。
前回のままのコードだと時刻が24時を過ぎた場合や分数が59分を超えた場合は27:67のように表示されてしまいます。
この問題を解決するために条件分岐のif文を使用していきます。

if m_t > 59
  m_t = m_t - 60
 m_h = m_h + 1
end
# 分数が59を超えた場合は時刻に1繰り上げ、分数からは60を引きます。
if m_h > 23
  m_h = m_h - 24
end
# 時刻に関しても23時を超えた場合は24を引き、24時間表示にします。



最後に出力時に00:00のにすることについて考えていきます。
今のままのコードでは24:3や8:22のように指定された24:03や08:22の形での出力が行えません。
そこでh_tとh_mそれぞれに値が一桁の場合は先頭に0を付け足すようにコードを加えます。

 h_t = h_t.to_s
 m_t = h_m.to_s
# 合計値が一桁かどうかを確かめるために数値を文字列に変更します。
if h_t.length == 1
  h_t = "0" + h_t
end
if h_m.length == 1
  h_m = "0" + h_m
end
# lengthメソッドによって桁数を確認し、1桁の場合は先頭に0を追加しています。

最後に合計時刻を出力するコードを追加すると完成です。

puts h_t + ":" + h_m
綺麗なコードを書くには

ここまでで以下のようなコードが完成しました。
このコードでも問題をクリアすることはできるのですが少しごちゃごちゃしていて読みにくさがあります。
そこで今回は①if文を1行で書く②+=を活用するの方法でより整理されたコードにしていきます。
①if文の省略について
if文は以下のように複数行のものを1行にまとめることができます。

  if h_t > 23
    h_t = h_t - 24
  end
h_t = h_t - 24 if h_t > 23


②+=の記号を使うと以下のような文章を省略して書くことができます。
h_tにh_tから24を引いた数値を代入する場合は重複が発生するので-=で引いた数がh_tであるということを示しています。

h_t = h_t - 24 if h_t > 23
h_t -= 24 if h_t > 23

これら2つの方法を使うと

n = gets.to_i
n.times do
  h_m, h_a, m_a = gets.split(" ")
  h, m = h_m.split(":").map(&:to_i)
  h_a = h_a.to_i
  m_a = m_a.to_i
  h_t = h + h_a
  m_t = m + m_a
  if m_t > 59
    m_t = m_t - 60
    h_t = h_t + 1
  end
h_t -= 24 if h_t > 23
    h_t = h_t.to_s
    m_t = m_t.to_s
m_h = "0" + m_h if m_h.length == 1
m_t = "0" + m_t if m_t.length == 1

      puts h_t + ":" + m_t
end

このようにコードを整理することができました。
問題に正解することはもちろん大切ですがプログラミングを仕事にするとなると整理されてわかりやすいコードを書くこともとても大切になってくると思うので常により良いコードを追い求めていきたいですね!

今回は以上となります。お疲れさまでした!


参考記事: Cランクレベルアップメニュー(言語選択) | レベルアップ問題集 | プログラミング学習サービス【paizaラーニング】