Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f31e2a1

Browse files
Pushing bitmask implementation to the repo - added more examples for testing
1 parent eb78909 commit f31e2a1

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

‎DynamicProgramming/BitMask.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
"""
2+
3+
This is a Python implementation for questions involving task assignments between people.
4+
Here Bitmasking and DP are used for solving this.
5+
6+
Question :-
7+
We have N tasks and M people. Each person in M can do only certain of these tasks. Also
8+
a person can do only one task and a task is performed only by one person.
9+
Find the total no of ways in which the tasks can be distributed.
10+
"""
11+
12+
from collections import defaultdict
13+
14+
15+
class AssignmentUsingBitmask:
16+
def __init__(self, task_performed, total):
17+
self.total_tasks = total # total no of tasks (N)
18+
19+
# DP table will have a dimension of (2^M)*N
20+
# initially all values are set to -1
21+
self.dp = [
22+
[-1 for i in range(total + 1)] for j in range(2 ** len(task_performed))
23+
]
24+
25+
self.task = defaultdict(list) # stores the list of persons for each task
26+
27+
# final_mask is used to check if all persons are included by setting all bits
28+
# to 1
29+
self.final_mask = (1 << len(task_performed)) - 1
30+
31+
def count_ways_until(self, mask, task_no):
32+
# if mask == self.finalmask all persons are distributed tasks, return 1
33+
if mask == self.final_mask:
34+
return 1
35+
36+
# if not everyone gets the task and no more tasks are available, return 0
37+
if task_no > self.total_tasks:
38+
return 0
39+
40+
# if case already considered
41+
if self.dp[mask][task_no] != -1:
42+
return self.dp[mask][task_no]
43+
44+
# Number of ways when we don't this task in the arrangement
45+
total_ways_util = self.count_ways_until(mask, task_no + 1)
46+
47+
# now assign the tasks one by one to all possible persons and recursively
48+
# assign for the remaining tasks.
49+
if task_no in self.task:
50+
for p in self.task[task_no]:
51+
# if p is already given a task
52+
if mask & (1 << p):
53+
continue
54+
55+
# assign this task to p and change the mask value. And recursively
56+
# assign tasks with the new mask value.
57+
total_ways_util += self.count_ways_until(mask | (1 << p), task_no + 1)
58+
59+
# save the value.
60+
self.dp[mask][task_no] = total_ways_util
61+
62+
return self.dp[mask][task_no]
63+
64+
def count_no_of_ways(self, task_performed):
65+
# Store the list of persons for each task
66+
for i in range(len(task_performed)):
67+
for j in task_performed[i]:
68+
self.task[j].append(i)
69+
70+
# call the function to fill the DP table, final answer is stored in dp[0][1]
71+
return self.count_ways_until(0, 1)
72+
73+
74+
if __name__ == "__main__":
75+
total_tasks = 5 # total no of tasks (the value of N)
76+
77+
# Example 1
78+
task_performed = [[1, 3, 4], [1, 2, 5], [3, 4]]
79+
print(
80+
AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
81+
task_performed
82+
)
83+
)
84+
85+
# Example 2
86+
task_performed = [[1, 2], [2, 3], [1, 3]]
87+
print(
88+
AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
89+
task_performed
90+
)
91+
)
92+
93+
# Example 3
94+
task_performed = [[1, 2, 3], [2, 3, 4], [1, 4, 5]]
95+
print(
96+
AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
97+
task_performed
98+
)
99+
)
100+
101+
# Example 4
102+
task_performed = [[1], [2], [3], [4], [5]]
103+
print(
104+
AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
105+
task_performed
106+
)
107+
)
108+
109+
# Example 5
110+
task_performed = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
111+
print(
112+
AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
113+
task_performed
114+
)
115+
)
116+
117+
# the list of tasks that can be done by M persons.
118+
task_performed = [[1, 3, 4], [1, 2, 5], [3, 4]]
119+
print(
120+
AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
121+
task_performed
122+
)
123+
)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /