12ヶ月の中の複数月の平均を求めるアルゴリズム

投稿者: Anonymous

お世話になります。

業務で、今度の四月から開始される『働き方改革』の中に、複数月の平均が80時間を超えてはならないと
いうのがあり、それを求めるためのツールをAccessで作成しています。

四月から始まり、三月で終わる一年の期間の中で、二ヶ月以上の連続した組み合わせ(4-5,4-5-6,4-5-6-7~1-2-3,2-3まで)の平均を算出するのですが、数を数えてみると合計で66パターンの組み合わせができてしまいます。これを人数分だけ計算するとなると、かなりの時間がかかると思います。
勿論、一つ一つ行って、一度でも80時間超えがあれば、そこで確認済みにすれば良い話ではあるのですが、これをもっと効率的にやりたいと思っています。

上記のような、『総当たりの平均』を求めるやり方で、もっと効率の良い方法はありますでしょうか?SQLなどでできれば、とてもエレガントだとは思いますが…。SQLの平均の記述が解らないのではなく、コードのようにループさせなくて済む方法です。

強引にコードに直すと、下記のようになると思います。

   Dim arr(11) As Long ' ここでは宣言しかしていませんが、既に中身があるものと思ってください。
   Dim d0 As Long, d1 As Long, d2 As Long
    Dim val As Double
    Dim flg As Boolean

    flg = False
    For d0 = 0 To 11 - 1
        For d1 = d0 + 1 To 12 - 1
            val = 0#
            For d2 = d0 To d1
                val = val + arr(d2)
                If (val / ((d1 - d0) + 1) > 80) Then
                    flg = True
                    GoTo End_for
                End If
            Next
        Next
    Next

End_for:

よろしくお願いいたします。

解決

『働き方改革』については、時間外労働の上限規制の「2~6ヵ月平均で80時間以内」とは?【労働基準法改正 2019】 の記事を参考にしました。

この記事によると、「複数月の平均が80時間を超えてはならない」というのは正確には「2ヵ月ないし6か月平均で80時間以内」ということで、
その意味は、“2ヵ月、3ヵ月、4ヵ月、5ヵ月、6か月のいずれの期間においても、月平均80時間以内にしなければならない”。

そうすると、平均を計算しないといけないパターンは、以下の45種類
2か月:11パターン(4月から、5月から、・・・、2月から)
3か月:10パターン(4月から、5月から、・・・、1月から)
4か月:9パターン(4月から、5月から、・・・、12月から)
5か月:8パターン(4月から、5月から、・・・、11月から)
6か月:7パターン(4月から、5月から、・・・、10月から)

月の時間外労働時間が80時間を超えているかどうかの判断にも計算時間がかかるので、80時間を超えるケースが見つかるまで、全てのパターンを順に計算してみる以下のような愚直なコードのほうが計算時間は短くなると思います。

Dim overtime(12) As Double ' 12か月(4月から3月まで)の時間外労働時間の配列(データは事前に入れられていると想定)
Dim numOfMonth as Integer, startMonth as Integer, ov as Integer
Dim val As Double
Dim flg As Boolean

flg = False
For numOfMonth = 2 To 6  '平均をとる月の数を、2から6まで変えて調べる
    For startMonth = 0 to 12-numOfMonth '
        val = 0#
        For ov = startMonth To startMonth + numOfMonth -1
            val = val + overtime(ov)
        Next ov
        If ((val / numOfMonth) > 80) Then '月平均時間外労働時間が80時間超えか?
            flg = True
            GoTo End_for
        End If
    Next startMonth
Next numOfMonth

End_for:
  ' flagの値に基づいて、結果を表示する
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *