I am trying to solve this task:
There are three datasets: first data on offices in cities: each city has a certain number of offices and each office has its own capacity of employees. Second, data on teams and open positions in these teams. Third, data on candidates for positions, showing their id, city and position.
We have to allocate applicants across teams and offices in such a way as to maximize the number of employees of one team located in one office together. At the same time, we have to minimize number of cases when there are less than two employees of a certain team in a certain office.
Example:
Input:
city_data:
city office_id capacity
New York A 3
New York B 2
New York C 6
Boston D 2
Boston E 5
team_data:
team_id position
alpha Manager
alpha Manager
alpha Engineer
alpha Engineer
alpha Engineer
alpha Engineer
alpha Designer
beta Engineer
beta Engineer
beta Engineer
gamma Designer
gamma Engineer
employees_data:
employee_id city position
1 New York Manager
2 New York Manager
3 New York Engineer
4 New York Engineer
5 New York Engineer
6 New York Engineer
7 New York Engineer
8 New York Designer
9 New York Designer
10 Boston Engineer
11 Boston Engineer
12 Boston Engineer
Possible output:
team_id employee_id position city office_id
alpha 1 Manager New York C
alpha 2 Manager New York C
alpha 3 Engineer New York C
alpha 4 Engineer New York C
alpha 5 Engineer New York C
alpha 6 Engineer New York B
alpha 8 Designer New York B
beta 10 Engineer Boston E
beta 11 Engineer Boston E
beta 12 Engineer Boston E
gamma 9 Designer New York A
gamma 7 Engineer New York A
I tried to solve this way:
- Sort the employee_data in decreasing order of the count of employees for each position and city.
- For each city and position, assign the employee_id to the team_id and office_id with the maximum capacity until it reaches the capacity limit.
- Repeat the step 2 until all employees are assigned to the team_id and office_id.
And wrote this code:
from collections import defaultdict
def allocate_employees(city_data, team_data, employee_data):
city_office_capacity = defaultdict(dict)
for city, office, capacity in city_data:
city_office_capacity[city][office] = capacity
team_positions = defaultdict(list)
for team, position in team_data:
team_positions[team].append(position)
employee_allocations = []
for employee, city, position in employee_data:
max_capacity = 0
max_office = None
for office, capacity in city_office_capacity[city].items():
if capacity > max_capacity:
max_capacity = capacity
max_office = office
city_office_capacity[city][max_office] -= 1
for team, positions in team_positions.items():
if position in positions:
employee_allocations.append((team, employee, position, city, max_office))
break
return employee_allocations
city_data = [("New York", "A", 3),
("New York", "B", 2),
("New York", "C", 6),
("Boston", "D", 2),
("Boston", "E", 5)]
team_data = [("alpha", "Manager"),
("alpha", "Manager"),
("alpha", "Engineer"),
("alpha", "Engineer"),
("alpha", "Engineer"),
("alpha", "Engineer"),
("alpha", "Designer"),
("beta", "Engineer"),
("beta", "Engineer"),
("beta", "Engineer"),
("gamma", "Designer"),
("gamma", "Engineer")]
employee_data = [(1, "New York", "Manager"),
(2, "New York", "Manager"),
(3, "New York", "Engineer"),
(4, "New York", "Engineer"),
(5, "New York", "Engineer"),
(6, "New York", "Engineer"),
(7, "New York", "Engineer"),
(8, "New York", "Designer"),
(9, "New York", "Designer"),
(10, "Boston", "Engineer"),
(11, "Boston", "Engineer"),
(12, "Boston", "Engineer")]
allocate_employees(city_data, team_data, employee_data)
But I get the wrong output:
[('alpha', 1, 'Manager', 'New York', 'C'),
('alpha', 2, 'Manager', 'New York', 'C'),
('alpha', 3, 'Engineer', 'New York', 'C'),
('alpha', 4, 'Engineer', 'New York', 'A'),
('alpha', 5, 'Engineer', 'New York', 'C'),
('alpha', 6, 'Engineer', 'New York', 'A'),
('alpha', 7, 'Engineer', 'New York', 'B'),
('alpha', 8, 'Designer', 'New York', 'C'),
('alpha', 9, 'Designer', 'New York', 'A'),
('alpha', 10, 'Engineer', 'Boston', 'E'),
('alpha', 11, 'Engineer', 'Boston', 'E'),
('alpha', 12, 'Engineer', 'Boston', 'E')]
I tried a greedy algorithm here, but maybe integer programming will do better, for example?