• 締切済み

複数時間情報の重複を求める

プログラミングの考え方に関する質問です。 例: 施設Aを、ユーザーaaa が11:00から15:00まで4時間使った。 施設Aを、ユーザーbbb が12:00から14:00まで2時間使った。 施設Aを、ユーザーccc が13:00から16:00まで3時間使った。 開始時間、終了時間、人数のパラメータが変数であるとして、 複数ユーザーで「施設Aを共用」していた時間を各ユーザーで調べたいと思います。 この例では[共用]時間は下記のようになります。 aaaは 12:00-15:00の3時間 bbbは 12:00-14:00の2時間 cccは 13:00-15:00の2時間 重複する時間の検出方法として、どのような方法がよいでしょうか。

みんなの回答

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.8

No6に大事なルーティーンが抜けていたので 少しお待ちを。

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.7

No6です。 もし、同じ人物が複数回出入りする場合は、 データを、 利用番号  氏名  入室時刻     退室時刻 1     aaa   2011/1/1 11:00 2011/1/1 17:00 2     bbb   2011/1/1 13:00 2011/1/1 15:00 3     ccc   2011/1/1 14:00 2011/1/1 15:30 4     ddd   2011/1/1 17:00 2011/1/1 19:00 5     eee   2011/1/1 9:00  2011/1/1 11:00 6     bbb   2011/1/1 16:30 2011/1/1 17:30 7     ccc   2011/1/1 16:50 2011/1/1 18:20 のように、利用番号フィールドを設定し、利用番号での 時刻検索をすれば氏名が複数出てくる上記の例でも、 ほぼそのままNo6のコードが流用できます。 プロシージャの引数は利用番号に変更します。 あるいは、プロシージャの中ですべての利用番号を 検索処理するかでしょう。その場合は、No6の プロシージャに、もう一つ上から利用番号を順次 抽出していくFor~Nextのループをかぶせる 必要があります。 やりかたはいろいろです。

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.6

Sheet1に以下のようにデータが入っているとします。 氏名  入室時刻     退室時刻 aaa   2011/1/1 11:00 2011/1/1 17:00 bbb   2011/1/1 13:00 2011/1/1 15:00 ccc   2011/1/1 14:00 2011/1/1 15:30 ddd   2011/1/1 17:00 2011/1/1 19:00 eee   2011/1/1 9:00  2011/1/1 11:00 一応、Subプロシージャに名前を渡せば、メッセージボックスで 時刻が表示されます。連続して名前を取り出す場合は、フラッグの 設定等に注意をする必要があります。 共用時間帯での人数、氏名は、ループ中の中で簡単に取り出せます。 中に一部コメントアウトしたものが残っていたりするものがあるか もしれません。ご容赦。たぶん、まともに動くとは思いますが。 何かあれば、補足してください。 プロシージャを関数に渡して、名前をループしてもいいかも しれません。あとは、応用してください。 Sub test1(strName As String) Dim ws As Worksheet Dim dIn As Date '開始日 Dim dOut As Date '終了日 Dim predStart As Date '一時保管用 Dim predEnd As Date '一時保管用 Dim dStart As Date '共用開始日 Dim dEnd As Date '共用終了日 Dim boolStart As Boolean '共用開始フラッグ Dim boolStartX As Boolean '特異点用共用開始フラッグ Dim i1 As Long Dim i2 As Long Dim i3 As Long Dim i4 As Long Dim i5 As Long Dim k As Long boolStart = False boolStartX = False Set ws = ThisWorkbook.Sheets("Sheet1") k = ws.Cells(Rows.Count, 1).End(xlUp).Row '最終行 For i1 = 2 To k '### 対象の検索 If ws.Cells(i1, 1).Value = strName Then '対象の入室時刻、退室時刻の取得 dIn = ws.Cells(i1, 2).Value dOut = ws.Cells(i1, 3).Value '### 共用開始時刻の検索1 For i2 = 2 To k If ws.Cells(i2, 1).Value <> strName Then If ws.Cells(i2, 2).Value <= dIn And ws.Cells(i2, 3).Value >= dIn Then predStart = dIn dStart = predStart boolStart = True ElseIf ws.Cells(i2, 2).Value >= dIn And ws.Cells(i2, 3).Value <= dOut Then predStart = ws.Cells(i2, 2).Value If predStart < dStart Then dStart = predStart boolStart = True End If End If End If Next i2 '### 共用開始時刻の検索2 '### 入室時一人で退室時刻と他の人の入室時刻が重なった場合の共用開始時刻 For i3 = 2 To k If ws.Cells(i3, 1).Value <> strName Then If boolStart = False Then If ws.Cells(i3, 2).Value = dOut And ws.Cells(i3, 2).Value > dIn Then dStart = dOut boolStartX = True End If End If End If Next i3 '### 共用終了時刻検索 If boolStart = True Then For i4 = 2 To k If ws.Cells(i4, 1).Value <> strName Then If ws.Cells(i4, 2).Value <= dOut And ws.Cells(i4, 3).Value >= dOut Then dEnd = dOut 'Exit for ElseIf ws.Cells(i4, 3).Value >= dIn And ws.Cells(i4, 3).Value <= dOut Then predEnd = ws.Cells(i4, 3).Value If predEnd > dEnd Then dEnd = predEnd 'Exit For End If ElseIf ws.Cells(i4, 2).Value >= dOut And ws.Cells(i4, 2).Value < dOut Then predEnd = ws.Cells(i4, 2).Value If predEnd > dEnd Then dEnd = predEnd End If End If End If Next i4 End If '### 入室時一人で退室時刻と他の人の入室時刻が重なった場合の共用終了時刻 If boolStartX = True Then For i5 = 2 To k If ws.Cells(i5, 1).Value <> strName Then If ws.Cells(i5, 2).Value = dOut And ws.Cells(i5, 2).Value > dIn Then dEnd = dOut 'Exit For End If End If Next i5 End If 'Exit For End If Next i1 If boolStart = True Then MsgBox strName & "の共用開始日は" & dStart & Chr(13) & "共用終了日は" & dEnd End If If boolStartX = True Then MsgBox strName & "の共用開始日は" & dStart & Chr(13) & "共用終了日は" & dEnd End If Set ws = Nothing End Sub

Viartril-S
質問者

お礼

ありがとうございます。 戴いたサンプルを読み解いて、参考にさせていただきます。 質問があるかもしれないので、もう少しの間この件をオープンにさせていただきたいと思います。

  • nicotinism
  • ベストアンサー率70% (1019/1452)
回答No.5

__時間帯→ aa□■■■■□□□■■ bb■■□□□■■□□□ cc■□□□□■■□■■ dd□□■■□□□□■■ もう一つ力技で行う方法。 上記を二次元配列に入れてあげて、For ~ Next の二重ループで 配列の値を判定して、それを別の変数にでも格納すれば 各人ごとに誰が同室だったかその時間帯は?までも求められそうですね。 時間帯の区切りは開始時刻からの経過時間を分単位で求めて 区切り時間単位(例 15分とか)で割った商と余りから出せば良さそう。

Viartril-S
質問者

お礼

回答ありがとうございます。参考になります。

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.4

   8 9 10 11 12 1 2 3 4 5 6 7 8 aaa       ・・・・・・・・・・ bbb          ・・・・ ccc            ・・・ ddd                ・・・・ eee   ・・・・・ 一つの例として上記のように退室と入室は一回とします。 表が崩れているかもしれませんが、aaaの入室時刻と eeeの退室時刻はおなじです。また、aaaの退室時刻と dddの入室時刻は同じです。上記は一つの例です。 入室時刻が、他の人の入室時刻と退室時刻の間に入っている ならばそれが共用の始まりの時刻となります。もし、 入室したときにだれもいなくて後から誰かが入室すれば、 そのときに入室した人の入室時刻が自分の共用の 始まりの時刻となります。これを自分以外のすべての 人について検索し、その中で一番最初の時刻を共用の 始まりの時刻とします。 上記の例のaaaの入室時刻とeeeの退室時刻が重なりますが、 これを共用時刻と判定するならば、eeeの共用の始まり時刻 は他の場合と別に判定するルーティーンが必要になります。 これらの共用始まりの時刻を検出したならば、フラッグを 立て、共用時刻の終わりの判定に利用します。別途判定する 場合にも別フラッグを立てます。 共用の終わりの時刻の判定は上記の場合と似たようなものです。 共用の始まりと終わりの時刻を検出したら、フラッグ別に 共用の始まりと終わりの時刻を出します。 一人の人物が入室、退室が複数回ある場合もほぼ同様の 処理でできますが、その場合、共用の始まりと終わりの セットが複数でる可能性があるので、このデータを どのようにファイルに格納するか考える必要はあります。 プログラムは、ループ処理の入れ子を行なうようになります。 >プログラミングの考え方に関する質問です。 ということなので、コードは載せませんが、必要ならば 載せます。 VB系(Excel、Access、Visual Basic)、あるいはC言語系 でもコードの流れは似たようなものです。 質問のようなプログラムは実際には結構いろいろな 場面で使われています。

Viartril-S
質問者

お礼

ありがとうございます。私のスキルから現実的なのかという点から考えようと思い、皆様の考え方を参考にさせていただきました。Proin654様の回答が、私の考えから漏れていた部分まで書いていただいており、大変素晴らしいと思いました。 今までは人手で時間を出していたのですがVB系(Excel)に移そうとしています。 もしよろしければ、サンプルをお見せいただけますか? Excelマクロになっていなくても、VB系コードからExcelへの移植はなんとかできると思います。

  • MARU4812
  • ベストアンサー率43% (196/452)
回答No.3

2人のユーザの各々1区間のみ取り出した時の 比較は、 シューティングゲームの当たり判定のように、 単純な不等号の判定を組み合わせてもできる でしょうし、 ・4点を昇順に並べて、 考えられるパターンは aaa aaa bbb bbb × 重なり無し aaa bbb aaa bbb ○ bbb~aaa aaa bbb bbb aaa ○ bbb~bbb bbb aaa bbb aaa ○ aaa~bbb bbb bbb aaa aaa × 重なり無し bbb aaa aaa bbb ○ aaa~aaa ・1点目と2点目が同じユーザなら重複なし ・ユーザが変わった点(2点目)から次の点(3点目)まで に限定できる気がします。そういったまとめ方を 考え出してもいいでしょう。 境界がぴったり一致した時(重なりの長さ0)だけ 除外した方がいいのかな。 # その場の思いつきなのでパターン抜けあったら指摘下さい。 中学生の数学レベルの知識があれば実現する方法は幾つか ありそうですね。円や図形の範囲が重なってる話なら 高校数学の方程式あたりの出番だけど、そこまで必要 無さそうです。

Viartril-S
質問者

お礼

回答ありがとうございます。参考になります。

  • nicotinism
  • ベストアンサー率70% (1019/1452)
回答No.2

__時間帯→ aa□■■■■□□□■■ bb■■□□□■■□□□ cc■□□□□■■□■■ dd□□■■□□□□■■ こんな風に□は未使用、■は使用中だとして □→0、■→1と置き換えて aa0,1,1,1,1,0,0,0,1,1 bb1,1,0,0,0,1,1,0,0,0 cc1,0,0,0,0,1,1,0,1,1 dd0,0,1,1,0,0,0,0,1,1 aaさんが使用中に共有していた時間を求める場合には aaさん以外の人の時間帯の論理和を求めて bb1,1,0,0,0,1,1,0,0,0 cc1,0,0,0,0,1,1,0,1,1 dd0,0,1,1,0,0,0,0,1,1 XX1,1,1,1,0,1,1,0,1,1 このXXとaaとを今度は、論理積で aa□■■■■□□□■■ XX■■■■□■■□■■ ↓ AA□■■■□□□□■■ ということかな?(等幅フォントで見てね) VBA なら Or、And 演算子に説明があります。ウェブ上なら『論理和、論理積』で検索を。 嫌いじゃないけど得意でもないので退散退散。

  • imogasi
  • ベストアンサー率27% (4737/17069)
回答No.1

質問説明が十分でないのでは。補足しておいたほうが良いのでは。 A施設についてB,C・・施設もあり、施設ごとに考えるのでしょうね。 ダブリは1日単位で考えるのか。当然日付の要素は必要で(日が違えば同じ時間帯でも該当しないだろう)データ上どうなっているのか。 利用時間はスタートとエンドとも何時単位で良いか(3/・45分に終るとか9/15にはじめるなどがあるのか。 例示データが不足ないしは実態の説明不足だろう。 ーー 珍しいいタイプで、相当手ごわいような気もする。このアルゴリズムは、数学や論理が得意な人の読む、質問コーナーに投稿するのが良いのでは。 ーー >人数のパラメータが 突然出てきているが、これはどういうこと? ーー 時間帯別重複人数ではなく、利用者別に重複時間を出すのか?

Viartril-S
質問者

お礼

質問内容をご理解いただけなくて残念です。 次回から気をつけます。 ありがとうございました。

関連するQ&A

専門家に質問してみよう