如何使用python在一个月内平均选择休假天数?

2024-10-17 06:31:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我会在一个日历月内随机给一个团队安排8天的假期。在

我想随机选择8天,休息日分配应该尽量均匀。例如,我的意思是,8天的假期不应该在每月的前8天集中。在

例如:[1,5,8,14,18,24,27,30]就是一个好的分布。 [1,2,3,4,26,27,28,29]不是一个好的分布。在

实际上,一个船员不能连续工作7天。每7天必须休息一天。在

所有的日子都一视同仁。船员也可以在周末工作。在

我想一天一天的休息。不是8个人同时在一起。在

你能推荐一种使用python实现这一点的算法吗?在

并非一个月的所有日子都可以休假。在

谨致问候


Tags: 算法团队我会问候日子船员
3条回答

使用^{}从序列中获取随机集。列出可用的天数,然后将其传递给.sample()函数:

import sample
daysoff = [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20]

picked = random.sample(daysoff, 8)

在上面的例子中,我使用了一个月的某一天,列表中省略了某些天(例如,星期天和一个月的最后10天),然后我们从该总体中随机选择8天。在

你应该把总天数平分。在

不管有多少天都在休息,不管需要多少天。在

from random import randint
def foo(l, n):
    dist = round(len(l)/n)
    return [randint(l[i*dist], l[(i+1)*dist-1]) for i in range(n)]

In [1]: days = [i for i in range(1,31)]
In [2]: foo(days, 8)
Out[2]: [1, 4, 6, 9, 13, 16, 20, 27]

In [3]: mylist = [i for i in range(500)]
In [4]: foo(mylist, 5)
Out[4]: [80, 147, 250, 346, 448]

舍入时会出现一些问题,列表索引可能会超出范围。在

这里的关键是:

Actually, a crew can't work 7 consecutive days. In every 7 days, there must be 1 day-off.

改写问题,每7天随机抽取2天(或根据需要将一个月分成四段时间)。然后保证你的分配是均匀的。按照Martijn Pieters的建议使用random.sample()。在

你可以从第一周开始使用这种方法生成两个值,如果你想一个接一个的话,就按顺序生成它们。在

编辑:

正如tcaswell所观察到的,仍然有一些情况下你会连续工作十天。为了解决这一问题,您可以每三天安排一天休假,创建一个10天的列表,并从不会使连续7天标准失效的天数子集中随机删除两天。在

或者,您可以继续使用原始算法生成列表,直到它符合条件为止,因为无论如何您都很可能得到一个有效的解决方案。你必须编写一个验证函数,但是这很容易做到,因为你只是在计算最长的连续天数。在

代码:

第二种选择的实现。在

import random
from itertools import chain
from itertools import count

def candidate(m):
    ''' Returns 2 days per week, in m days, where m is the length of the month. '''
    weeks = weeksmaker(m)
    return sorted(list(chain(*[random.sample(week, 2) for week in weeks])))

def weeksmaker(m):
    ''' Divides a month up into four weeks, randomly assigning extra days to weeks. '''
    weeks = [range(i, i+7) for i in xrange(1,29,7)]
    for i in range(m - 28):
        weeks[random.randint(1, len(weeks))-1].append(i)
    c = count(1)
    return [[c.next() for day in week] for week in weeks]

def valid(days, c):
    ''' Validity check. Cant work more than c consecutive days. '''
    for i in xrange(1, len(days)):
        if days[i] - days[i-1] > c:
            return False
    else:
        return True

def daysoff(m, n, c):
    ''' In month length m, need n days off, cant work more than c consecutive days. '''
    while True:
        days = candidate(n)
        if valid(days, c):
            return days

>>> for i in range(28, 32):
...     daysoff(i, 8, 7)
... 
[6, 7, 10, 14, 18, 20, 27, 28]
[4, 7, 10, 13, 19, 21, 23, 24]
[2, 4, 9, 13, 15, 20, 25, 27]
[1, 3, 9, 12, 18, 19, 24, 28]

相关问题 更多 >