例えば、1:00-2:00のような時間帯の情報があるとして、2つの時間帯AとBが重なっているかどうかを調べたい場合。
Aが1:00-2:00、Bが1:30-2:30だったら重なっている、Bが2:10-2:40なら重なっていない…といった具合です。
重なっている例 01:00 01:30 02:00 02:30 | | | | A <-----------------> | B | <----------------->
重なっていない例 01:00 01:30 02:00 02:30 | | | | A <-----------------> | B | | | <------->この「重なっているか否か」を判断する方法について解説します。
これからドヤ顔で解説しますが、別に本邦初公開でも何でもありません。
「そんなもん知っとるわボケ」と思っても優しく見守ってください。
準備
まず、「範囲」を示す型を準備します。ここではTypeScriptのinterface
を使いますが、C言語の構造体のようなものだと思ってください。interface Range { begin: number; end: number; }とりあえず
begin
≦end
だと仮定しておきます。次に「重なっている」の定義です。 上で1つだけ重なっている例を挙げましたが、全部でこの4種類があります。
Aが先 A <-----------------> B <----------------->
Bが先 A <-----------------> B <----------------->
AがBを包含 A <---------------------> B <--------->
BがAを包含 A <---------> B <--------------------->
コード
では実際のコードです。先程の4つのケースをすべて網羅するとこんな感じ?とりあえず境界が一致している場合のような細かいケースは考えず、大まかなロジックだけ見てください。
interface Range { begin: number; end: number; } function overlapped(a: Range, b: Range): boolean { if (a.begin < b.begin && a.end > b.begin && a.end < b.end) { // Aが先 return true; } if (b.begin < a.begin && b.end > a.begin && b.end < a.end) { // Bが先 return true; } if (a.begin < b.begin && a.end > b.end) { // AがBを包含 return true; } if (b.begin < a.begin && b.end > a.end) { // BがAを包含 return true; } // どれでもなければ重なっていない return false; }なんかややこしいですね。もうちょっと簡単にできないでしょうか。
こうしましょう
もっと簡単に判定できる方法があります。interface Range { begin: number; end: number; } function overlapped(a: Range, b: Range): boolean { if (a.end < b.begin) { // 重なっていない return false; } if (b.end < a.begin) { // 重なっていない return false; } // どちらでもなければ重なっている return true; }これだけです。
一応解説をしますが、逆転の発想ですね。重なっていない場合を考えます。
重なっている場合はいろいろ面倒なのに対して、重なっていない場合はこの2通りだけです。
Aが先 A <------> B <------>
Bが先 A <------> B <------>そして最初に
begin
≦end
という前提条件をつけておいたので、純粋に「a.end
とb.begin
」、「b.end
とa.begin
」の2つを比較するだけで済みます。何かのときに役に立つかも知れませんので覚えておいてください。
0 件のコメント:
コメントを投稿