我有一个应用程序,可以将员工分配给他们指定的任务。问题是如何在一周内为每位员工随机分配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
等等......
总是缺少员工。
答案 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名员工:
这并不是同样的传播。我建议的是:
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);
}
这将提供这种传播:
您的代码问题在于您希望在循环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人工作。