お題:時間帯重複チェック(応用編)を解いてみた。

はじめに

先日解いた「時間帯重複チェック」の応用編(「お題:時間帯重複チェック(応用編) - No Programming, No Life」)が出題されていたので、こちらも解いてみました。

コードは次の通りです。

実装手順

第一ステップ

前回のお題を解くときに、開始時刻と終了時刻をRange化して「時間帯」を表現しました。
ただし、少しサボって「時間帯」クラスを作っていなかったので、MyDurationクラスを作成して「開始時刻 <= 終了時刻」のチェックをMyDurationのコンストラクタ内に記述しました。

第二ステップ

追加仕様1:「重複していた場合には、その重複している時間帯を必要分だけ返すようする」は、複数の時間帯をArrayListに入れてから、ArrayList内の時間帯のすべてのペアに対して重なりを求める方法で対応しました。
rawListを作る部分のコードが該当箇所です。

第三ステップ

追加仕様2: 「返却する時間帯は開始時間が早いものから順に並べ替える」は、MyDurationにComparableを実装して、compareToを定義することで対応しました。
compareToはrawListをソートする箇所で使用しています。

第四ステップ

「同じ時間帯が2回以上重複している場合でも一つの時間帯とする」は、MyDuration同士のOR演算を定義することで対応しました。また、概念的に対になるAND演算も定義しました。

OR演算とAND演算の定義は次の通りです。

  • OR演算( orメソッド )
    • 重なりがある場合は両方を包含する一つの時間帯にまとめて、一要素のArrayListを返す。
    • 重なりがない場合は二つの時間帯のままにして、二要素のArrayListを返す。
  • AND演算( andメソッド )
    • 重なりがある場合は両方の共通部分を一つの時間帯にまとめて、一要素のArrayListを返す。
    • 重なりがない場合は要素なしのArrayListを返す。

OR演算は、rawList内のMyDurationを先頭から順に取り出して、取り出したMyDurationをresultListの末尾のMyDurationに結合する箇所で使用しています。

おわりに

今回のお題は、RangeのOR演算を表現する方法で悩みました。RangeにはAND演算相当のintersectがあるので、OR演算に相当するメソッドが簡単に見つかると思っていたのですがありませんでした。
Rangeには元々、andメソッドとorメソッドがないので、プログラミングの世界では範囲の和に関する最適な概念がないのかも知れません。スッキリ当てはまる概念をお持ちの方はアドバイスを頂けると幸いです。