Skip to content

Commit 16f8da5

Browse files
authored
Merge pull request prabhupant#312 from aadityachapagain/master
Bit Masking using Dynamic programming
2 parents 1939994 + d7b52a0 commit 16f8da5

2 files changed

Lines changed: 164 additions & 0 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
"""
2+
Consider the below problems statement.
3+
4+
There are 100 different types of caps each having a unique id from 1 to 100. Also,
5+
there are ‘n’ persons each having a collection of a variable number of caps.
6+
One day all of these persons decide to go in a party wearing a cap but to look unique
7+
they decided that none of them will wear the same type of cap. So, count the total number
8+
of arrangements or ways such that none of them is wearing the same type of cap.
9+
10+
"""
11+
12+
# Python program to find number of ways to wear hats
13+
from collections import defaultdict
14+
15+
16+
class AssignCap:
17+
18+
# Initialize variables
19+
def __init__(self):
20+
21+
self.allmask = 0
22+
23+
self.total_caps = 100
24+
25+
self.caps = defaultdict(list)
26+
27+
# Mask is the set of persons, i is the current cap number.
28+
def count_ways_util(self, dp, mask, cap_no):
29+
30+
# If all persons are wearing a cap so we
31+
# are done and this is one way so return 1
32+
if mask == self.allmask:
33+
return 1
34+
35+
# If not everyone is wearing a cap and also there are no more
36+
# caps left to process, so there is no way, thus return 0;
37+
if cap_no > self.total_caps:
38+
return 0
39+
40+
# If we have already solved this subproblem, return the answer.
41+
if dp[mask][cap_no] != -1:
42+
return dp[mask][cap_no]
43+
44+
# Ways, when we don't include this cap in our arrangement
45+
# or solution set
46+
ways = self.count_ways_util(dp, mask, cap_no + 1)
47+
48+
# assign ith cap one by one to all the possible persons
49+
# and recur for remaining caps.
50+
if cap_no in self.caps:
51+
52+
for ppl in self.caps[cap_no]:
53+
54+
# if person 'ppl' is already wearing a cap then continue
55+
if mask & (1 << ppl):
56+
continue
57+
58+
# Else assign him this cap and recur for remaining caps with
59+
# new updated mask vector
60+
ways += self.count_ways_util(dp, mask | (1 << ppl), cap_no + 1)
61+
62+
ways = ways % (10**9 + 7)
63+
64+
# Save the result and return it
65+
dp[mask][cap_no] = ways
66+
67+
return dp[mask][cap_no]
68+
69+
def count_ways(self, N):
70+
71+
# Reads n lines from standard input for current test case
72+
# create dictionary for cap. cap[i] = list of person having
73+
# cap no i
74+
for ppl in range(N):
75+
76+
cap_possessed_by_person = map(int, input().strip().split())
77+
78+
for i in cap_possessed_by_person:
79+
80+
self.caps[i].append(ppl)
81+
82+
# allmask is used to check if all persons
83+
# are included or not, set all n bits as 1
84+
self.allmask = (1 << N) - 1
85+
86+
# Initialize all entries in dp as -1
87+
dp = [[-1 for j in range(self.total_caps + 1)] for i in range(2 ** N)]
88+
89+
# Call recursive function countWaysUtil
90+
# result will be in dp[0][1]
91+
print(self.count_ways_util(dp, 0, 1,))
92+
93+
# Driver Program
94+
95+
96+
def main():
97+
No_of_people = int(input()) # number of persons in every test case
98+
99+
AssignCap().count_ways(No_of_people)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# code to find if given string
2+
# is K-Palindrome or not
3+
4+
"""
5+
Explanation
6+
7+
Process all characters one by one staring from either from left or right sides of both strings.
8+
Let us traverse from the right corner, there are two possibilities for every pair of character being traversed.
9+
10+
If last characters of two strings are same, we ignore last characters and get count for remaining strings.
11+
So we recur for lengths m-1 and n-1 where m is length of str1 and n is length of str2.
12+
If last characters are not same, we consider remove operation on last character of first string and
13+
last character of second string, recursively compute minimum cost for the operations and take minimum of two values.
14+
Remove last char from str1: Recur for m-1 and n.
15+
Remove last char from str2: Recur for m and n-1.
16+
"""
17+
18+
# Find if given string
19+
# is K-Palindrome or not
20+
21+
22+
def is_kpalrec(str1, str2, m, n):
23+
24+
# If first string is empty,
25+
# the only option is to remove
26+
# all characters of second string
27+
if not m:
28+
return n
29+
30+
# If second string is empty,
31+
# the only option is to remove
32+
# all characters of first string
33+
if not n:
34+
return m
35+
36+
# If last characters of two strings
37+
# are same, ignore last characters
38+
# and get count for remaining strings.
39+
if str1[m - 1] == str2[n - 1]:
40+
return isKPalRec(str1, str2, m - 1, n - 1)
41+
42+
# If last characters are not same,
43+
# 1. Remove last char from str1 and recur for m-1 and n
44+
# 2. Remove last char from str2 and recur for m and n-1
45+
# Take minimum of above two operations
46+
res = 1 + min(is_kpalrec(str1, str2, m - 1, n), # Remove from str1
47+
(is_kpalrec(str1, str2, m, n - 1))) # Remove from str2
48+
49+
return res
50+
51+
# Returns true if str is k palindrome.
52+
53+
54+
def is_kPal(string, k):
55+
revStr = string[::-1]
56+
l = len(string)
57+
58+
return (is_kpalrec(string, revStr, l, l) <= k * 2)
59+
60+
61+
# Driver program
62+
string = "acdcb"
63+
k = 2
64+
65+
print("Yes" if is_kPal(string, k) else "No")

0 commit comments

Comments
 (0)