在一周内随机分配员工休息日

时间:2016-03-08 08:13:37

标签: c#

我有一个应用程序,可以将员工分配给他们指定的任务。问题是如何在一周内为每位员工随机分配day-off day。该系统必须与至少7名员工合作。

示例:

Employee | Day Off
Emp 1    | Sun
Emp 2    | Wed
Emp 3    | Tue
Emp 4    | Mon
Emp 5    | Thu
Emp 6    | Sat
Emp 7    | Fri

但是如果员工人数高于默认值。 2名员工day-off必须有1天的改动。

示例1,另外还有1名员工

Employee | Day Off
Emp 1    | Sun
Emp 2    | Wed
Emp 3    | Tue
Emp 4    | Mon
Emp 5    | Thu
Emp 6    | Sat
Emp 7    | Fri
Emp 8    | Tue

示例2,另外还有2名员工

Employee | Day Off
Emp 1    | Tue
Emp 2    | Thu
Emp 3    | Sun
Emp 4    | Mon
Emp 5    | Wed
Emp 6    | Fri
Emp 7    | Sat
Emp 8    | Tue
Emp 9    | Sun

示例3,另外3名员工

Employee | Day Off
Emp 1    | Thu
Emp 2    | Sat
Emp 3    | Fri
Emp 4    | Mon
Emp 5    | Sun
Emp 6    | Wed
Emp 7    | Tue
Emp 8    | Tue
Emp 9    | Sun
Emp 10   | Wed

等等..

我希望系统随机生成。是否有任何代码算法可以解决此问题?谢谢!

  

更新

这就是我的尝试。

// Note that getActiveEmployee() returns List<Employee> object.
List<Employee> activeEmployees = this.GetActiveEmployees(); 

List<Employee> assignedEmployees = new List<Employee>();

// Set collection of employee which has no day off 
// from active employee list.
List<Employee> hasNoOffEmployees = new List<Employee>();
hasNoOffEmployees = activeEmployees; 

//  7 Days a week.
// Assumption: Start DayofWeek is sunday.
for (int x = 0; x < 7; x++)
{
     // Get random employee from hasNoOffEmployees.
     int eidx = rnd.Next(hasNoOffEmployees.Count);
     Employee selEmpHasOff = hasNoOffEmployees[eidx];

     foreach (Employee employee in activeEmployees)
     {
          if (selEmpHasOff == employee)
          {
               assignedEmployees.Add(employee);
               hasNoOffEmployees.Remove(selEmpHasOff);
               break;
          }
     }
}

day-off的给定结果将始终如下。

示例:

A - 有7名实际员工

Employee | Day Off
Emp 2    | Sun
Emp 4    | Mon
Emp 3    | Tue
Emp 1    | Wed
Emp 7    | Thu
Emp 6    | Fri
Emp 5    | Sat

B - 有8名实际员工。

Employee | Day Off
Emp 7    | Sun
Emp 6    | Mon
Emp 5    | Tue
Emp 4    | Wed
Emp 3    | Thu
Emp 8    | Fri
Emp 2    | Sat

C - 有9名实际员工。

Employee | Day Off
Emp 8    | Sun
Emp 3    | Mon
Emp 9    | Tue
Emp 4    | Wed
Emp 6    | Thu
Emp 7    | Fri
Emp 2    | Sat

等等......

总是缺少员工。

2 个答案:

答案 0 :(得分:2)

为确保尽可能均匀地随机分配休假日,您可以执行以下操作:

public enum DayOfWeek { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday };

public class Employee
{
    public DayOfWeek DayOff;
}

public class DayOffAllocator
{
    Random _random = new Random();
    DayOfWeek[] _daysOff = (DayOfWeek[])Enum.GetValues(typeof(DayOfWeek));
    List<DayOfWeek> _availableDaysOff = new List<DayOfWeek>();

    public void AllocateDayOff(Employee employee)
    {
        if (!_availableDaysOff.Any())
            _availableDaysOff = new List<DayOfWeek>(_daysOff);
        int index = _random.Next(_availableDaysOff.Count);
        employee.DayOff = _availableDaysOff[index];
        _availableDaysOff.RemoveAt(index);
    }
}

然后您可以通过以下方式使用它:

public class Program
{
    public static void Main(string[] args)
    {
        Employee[] employees = new Employee[123]
            .Select(employee => new Employee()).ToArray();

        DayOffAllocator dayOffAllocator = new DayOffAllocator();
        foreach(var employee in employees)
        {
            dayOffAllocator.AllocateDayOff(employee);
        }
        Dictionary<DayOfWeek, int> dist = ((DayOfWeek[])Enum.GetValues(typeof(DayOfWeek)))
            .ToDictionary(k => k, v => employees.Count(x => x.DayOff == v));
    }
}

您会注意到dist中显示的分布对于示例123员工来说尽可能均匀 - 3个随机日将有17名员工休假,其余4个随机日将有18名员工拥有该分配休息日。

答案 1 :(得分:0)

如果我理解正确,您希望随机为您的员工分配一天。假设这可能是您的班级Employee的简化版本:

public class Employee
{
    public string Name { get; set; }
    public DayOfWeek dayOff { get; set; }
    public override string ToString()
    {
        return "I'm " + Name + " and I don't work on " + dayOff;
    }
}

此代码将完美地完成工作:

List<Employee> myWorkers = new List<Employee>
{
    new Employee {Name = "Mary"},
    new Employee {Name = "Chris"},
    new Employee {Name = "Peter"},
    new Employee {Name = "John"},
    new Employee {Name = "Xavier"},
    new Employee {Name = "Matt"},
    new Employee {Name = "Oscar"},
    new Employee {Name = "Jules"},
    new Employee {Name = "Sarah"},
    new Employee {Name = "Cola"},
    new Employee {Name = "Donald"},
    new Employee {Name = "Mick"},
    new Employee {Name = "Jack"},
    new Employee {Name = "Thomas"}
};

Random r = new Random();

foreach (Employee employee in myWorkers)
{
    Thread.Sleep(50);
    employee.dayOff = (DayOfWeek) r.Next(7);
}
foreach (Employee employee in myWorkers)
{
    Console.Out.WriteLine(employee.ToString());
}

哪个输出(你的和我的不一样:它是随机的):

  

我是玛丽,我星期六不上班

     

我是克里斯,我周四不工作

     

我是彼得,我不在星期二工作

     

我是约翰,我周二不工作

     

我是泽维尔,我不在周三工作

     

我是马特,我不在周日工作

     

我是奥斯卡,我周三不上班

     

我是朱尔斯,我周五不工作

     

我是莎拉,我星期六不上班

     

我是可乐,我周五不工作

     

我是唐纳德,我星期六不上班

     

我是Mick,我周五不工作

     

我是杰克,我周一不工作

     

我是托马斯,我星期三不上班

但你可以注意到,超过14名员工:

  • 周六21,43%
  • 周四7,14%
  • 周二14,29%
  • 周三21,43%
  • 周日7,14%
  • 周五21,43%
  • 周一7,14%

这并不是同样的传播。我建议的是:

int i = 0;
// Easy suffle of the list, random enough for this usage
foreach (Employee employee in myWorkers.OrderBy(a => Guid.NewGuid()))
{
    employee.dayOff = (DayOfWeek) ((i++)%7);
}

这将提供这种传播:

  • 周二14,29%
  • 周日14,29%
  • 周四14,29%
  • 周一14,29%
  • 周五14,29%
  • 周六14,29%
  • 周三14,29%

您的代码问题在于您希望在循环for (int x = 0; x < 7; x++)中浏览一周中的7天,但是您只需使用以下代码检查列表中的7位第一名员工:

int eidx = rnd.Next(hasNoOffEmployees.Count);
Employee selEmpHasOff = hasNoOffEmployees[eidx];

foreach (Employee employee in activeEmployees)
{
    if (selEmpHasOff == employee)
    {
       assignedEmployees.Add(employee);
       hasNoOffEmployees.Remove(selEmpHasOff);
       break;
    }
}

这就是为什么你没有让你的名单中的超过7人工作。