裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

日程調整

2015年05月12日 | ブログラミング

各人(name)の拘束日時(date, begin, end) について以下のような予定表がある(3人以上でもよい)。

  name       date begin   end
1  新井 2015/04/27 08:30 17:00
2  新井 2015/04/28 09:00 16:30
3  新井 2015/04/29 08:00 17:00
4  新井 2015/04/30 09:00 16:30
5  新井 2015/04/30 17:00 21:00
6  新井 2015/05/01 08:00 16:30
7  新井 2015/05/01 18:00 21:00
8  新井 2015/05/02 08:30 16:30
9  新井 2015/05/04 08:00 17:30
10 新井 2015/05/05 11:00 15:30
11 古田 2015/04/27 09:30 16:00
12 古田 2015/04/27 19:30 22:00
13 古田 2015/04/28 08:30 17:00
14 古田 2015/04/28 17:30 19:30
15 古田 2015/04/29 18:00 22:00
16 古田 2015/04/30 10:00 17:00
17 古田 2015/05/01 17:00 20:00
18 古田 2015/05/02 18:00 19:30
19 古田 2015/05/03 08:00 17:30
20 古田 2015/05/04 14:00 19:30
21 古田 2015/05/05 08:30 18:00

リストされている人全員が自由な時間が,連続する 3 時間以上となる,直近の日時を調べよ。ただし,6:00~22:00 の範囲であること。

func = function(s) {
  # 6:00 ~ 22:00 までを 30 分を 1 コマとして何コマ目かを数字で表す
  # 6:00~6:30 ==> 1, 6:30~7:00 ==> 2, ... , 21:30~22:00 ==> 32
  hm = as.integer(unlist(strsplit(s, ":")))
  hm[1] * 2 + (hm[2] == 30) - 11
}
inv = function(i) {
  # 上記 func の逆関数コマ数を表す数字から,コマの開始時間を求める
  sprintf("%02i:%02i", (i-1)%/%2+6, (i-1)%%2*30)
}

d = data.frame(stringsAsFactors = FALSE,  # スケジュール表(文字列で)
name = c("新井", "新井", "新井", "新井", "新井", "新井", "新井",
"新井", "新井", "新井", "古田", "古田", "古田", "古田", "古田", "古田",
"古田", "古田", "古田", "古田", "古田"),

date = c("2015/04/27", "2015/04/28", "2015/04/29", "2015/04/30",
"2015/04/30", "2015/05/01", "2015/05/01", "2015/05/02",
"2015/05/04", "2015/05/05", "2015/04/27", "2015/04/27",
"2015/04/28", "2015/04/28", "2015/04/29", "2015/04/30",
"2015/05/01", "2015/05/02", "2015/05/03", "2015/05/04",
"2015/05/05"),

begin = c("08:30", "09:00", "08:00", "09:00", "17:00", "08:00",
"18:00", "08:30", "08:00", "11:00", "09:30", "19:30", "08:30",
"17:30", "18:00", "10:00", "17:00", "18:00", "08:00", "14:00",
"08:30"),

end = c("17:00", "16:30", "17:00", "16:30", "21:00", "16:30",
"21:00", "16:30", "17:30", "15:30", "16:00", "22:00", "17:00",
"19:30", "22:00", "17:00", "20:00", "19:30", "17:30", "19:30",
"18:00"))


d = d[order(d[, 2]), ]           # 月日で並べ替え
n = nrow(d)                      # スケジュールの総数(行数)
t.begin = sapply(d[, 3], func)   # 拘束開始時間をコマ数に変換
t.end = sapply(d[, 4], func) - 1 # 拘束終了時間をコマ数に変換
begin = 1                        # 1 日分がどこからどこまでか
day = d[begin, 2]
for (i in 1:(n - 1)) {
  if (d[i, 2] != d[i + 1, 2]) {
    begin = c(begin, i + 1)
  }
}
end = c(begin[-1] - 1, n)
for (i in seq_along(begin)) {    # 日付ごとにチェック
  time.table = integer(32)       # コマ
  for (j in begin[i]:end[i]) {   # 拘束コマを 1 で埋める
    time.table[t.begin[j]:t.end[j]] = 1
  }
  k = 1                          # 連続する自由なコマ数を求める
  while (k < 32) {
    while (time.table[k] == 1) {
      k = k + 1
      if (k > 32) break
    }
    ks = k
    if (k > 32) break
    while (time.table[k] == 0) {
      k = k + 1
      if (k > 32) break
    }
    free.time = (k - ks) / 2     # コマ数を時間に直す(2 コマで 1 時間)
    if (free.time >= 3) {        # 自由時間が 3 時間以上なら結果出力
      cat(sprintf("%s の %s ~ %s の %.1f 時間\n", d[j, 2], inv(ks), inv(k), free.time))
      break
    }

  }
  if (free.time >= 3) break
}

実行結果

2015/04/30 の 06:00 ~ 09:00 の 3.0 時間

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村