このページについて

このページは、paiza ラーニング内に開設されているコンテンツ「レベルアップ問題集」で取り扱われているプログラミング課題について、独自の見解を述べたものです。

見解については、paizaラーニングの規約に基づき、許可されている範囲でのみ公開していますが、その内容については paiza とは一切関係なく、また paiza の立場を反映したものではありませんのでご注意ください。

挑戦する課題

レベルアップ問題集日付セットから「翌営業日 – その2 (paizaランク B 相当)」を取り上げます。

以下は、問題公開 Web ページからの引用です。

問題

西暦2019年M月D日d曜日の翌営業日の日付を表示してください。

営業日は、休業日ではない日です。
休業日とは、土曜日、日曜日、または、内閣府の定める国民の祝日・休日のことです。

ただし、上記の条件を満たさない日は、休業日ではありません。例えば、官公庁や一般企業が休みとなる1月2日, 1月3日, 12月31日は休業日ではないものとします。

参考: 内閣府 「国民の祝日」について

★筆者注★
既に上記リンクは2020年以降に更新されていますので、2019年は次のデータを用いてください(振替休日含む)。
  • 1月:1日, 14日
  • 2月:11日
  • 3月:21日
  • 4月:29日, 30日
  • 5月:1日, 2日, 3日, 4日, 5日, 6日
  • 7月:15日
  • 8月:11日, 12日
  • 9月:16日,23日
  • 10月:14日, 22日
  • 11月:3日, 4日, 23日

入力される値

整数MとD、英文字列dが次のように、スペース区切りで1行で入力されます。

期待する出力

以下のような形式で、答えを出力してください。

  • AとBは、整数です。

条件

すべてのテストケースにおいて、以下の条件をみたします。

  • 1 ≦ M ≦ 12
  • 1 ≦ D ≦ 31
  • dは、「SUN, MON, TUE, WED, THU, FRI, SAT」の7つの英文字列のうち、1つが入力されます。
  • ただし、M=12, D=31, d=TUEのデータは与えられません。(年越しを考慮する必要はありません)
  • ただし、M=2, D=31, d=MON のように、この世に存在しない日付は入力されません。(2月は28日までです)

考え方

まず、基本となるデータは辞書、もしくは配列の形で準備しておく。
たとえば、国民の祝日・振替休日はこのような感じ。

 

これは、 [Int: [Int]] 型の辞書、つまり辞書の value が配列になっている辞書だが、このようにしておくことで、ある月の祝日を計算するのが楽になる。
たとえば、 m を月数とするとき

 

このようにすれば、ある月 m の祝日は [Int] の配列として求めることができる。あとは、配列のメソッドである contains を使うことによって、ある日 d が祝日・振替休日か否かを判断すれば良い。

次の営業日の計算は次のように行なった。ここで、現在の曜日を w とする。
まずは、曜日に対応する翌営業日の辞書 wd を準備する。
次に、曜日ラベルを wdd という形で用意しておく。

wdd のうち、現在の曜日に相当するインデックスは、 firstIndef(of:) を使って求める。これに、次の営業日までの日数を加算し、7 での剰余を求めれば次の営業日の曜日となる。
 

注意しなければいけないのは、5月のように連休が続く時の処理。ここでは、ある日が休日だった時に処理を行った場合には、再度その処理を行うように repeat-while で処理をしたが、もっと賢い例があるかもしれない。

月跨ぎの処理については、過去問と同じなのでそれを流用する。

翌営業日 – その1 (paizaランク C 相当)

解答例