Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to check all tasks can be executed using given server cores or not in Python
Suppose we have two lists: cores and tasks. The cores[i] indicates the number of cores available in the ith server, and tasks[i] indicates the number of cores needed to execute that task. Each task must be run on only one server, and a server may have multiple tasks to run. We need to check whether it's possible to run all tasks with the given server cores.
For example, if cores = [10, 7] and tasks = [7, 3, 2, 2, 1], the output will be True because we can assign tasks[0] (7 cores) and tasks[1] (3 cores) to the first server with 10 cores, and the remaining tasks to the second server with 7 cores.
Approach Using Backtracking
We'll use a recursive backtracking approach that tries to assign each task to available servers ?
Algorithm Steps
- If no tasks remain, return
True(all tasks assigned successfully) - For each server, check if it has enough cores for the current task
- If yes, assign the task temporarily and recursively solve for remaining tasks
- If the recursive call succeeds, return
True - Otherwise, backtrack by unassigning the task and try the next server
- If no server can accommodate the task, return
False
Example Implementation
def can_execute_all_tasks(cores, tasks):
if not tasks:
return True
for i in range(len(cores)):
if cores[i] >= tasks[0]:
cores[i] -= tasks[0] # Assign task to server i
if can_execute_all_tasks(cores, tasks[1:]):
cores[i] += tasks[0] # Restore for other test cases
return True
cores[i] += tasks[0] # Backtrack
return False
# Test case 1
cores = [10, 7]
tasks = [7, 3, 2, 2, 1]
result = can_execute_all_tasks(cores.copy(), tasks)
print(f"Can execute all tasks: {result}")
# Test case 2
cores2 = [5, 3]
tasks2 = [6, 4, 2]
result2 = can_execute_all_tasks(cores2.copy(), tasks2)
print(f"Can execute all tasks: {result2}")
Can execute all tasks: True Can execute all tasks: False
How It Works
The algorithm works as follows ?
- Base Case: If the tasks list is empty, all tasks have been successfully assigned
- Try Each Server: For each server, check if it has sufficient cores for the current task
- Assign and Recurse: Temporarily reduce the server's available cores and recursively solve for remaining tasks
- Backtrack: If the assignment doesn't lead to a solution, restore the server's cores and try the next server
Optimized Version with Sorting
We can optimize by sorting tasks in descending order to try larger tasks first ?
def can_execute_all_tasks_optimized(cores, tasks):
# Sort tasks in descending order for better pruning
tasks = sorted(tasks, reverse=True)
def backtrack(task_index):
if task_index == len(tasks):
return True
current_task = tasks[task_index]
for i in range(len(cores)):
if cores[i] >= current_task:
cores[i] -= current_task
if backtrack(task_index + 1):
cores[i] += current_task
return True
cores[i] += current_task
return False
return backtrack(0)
# Test the optimized version
cores = [10, 7]
tasks = [7, 3, 2, 2, 1]
result = can_execute_all_tasks_optimized(cores.copy(), tasks)
print(f"Optimized result: {result}")
Optimized result: True
Time and Space Complexity
- Time Complexity: O(n^m) where n is the number of servers and m is the number of tasks
- Space Complexity: O(m) for the recursion stack depth
Conclusion
This backtracking solution efficiently determines if all tasks can be executed using available server cores. The optimized version with sorted tasks provides better performance by trying larger tasks first, leading to faster pruning of invalid branches.
