Currently I was trying to code some algorithm that one of my friend told me to do. In that algorithm I needed the code of a power-set generator. I first tried to code in my own way but it proved to be not so much simple. Then I found another simple logic to generate power-set. Logic is simple if you want the power-set of a set with n number of elements then just generate all the combination of n boolean variables.
Suppose you want the power-set of 3 variables a,b,c. Then take 3 boolean variables and generate their all their possible combination. For 3 variables it will be:
Now the problem is how to generate these boolean variables combination. Here we can use bitwise operator. We only need right/left shift operator and the bitwise AND(&) operator for masking purpose. Actually we will iterate a loop from 0 to (2^n) where n is the number of elements in the set and then scanning n leftmost element of each loop count and check whether it is 1 or 0.
For 3 variables we will use a loop i:=0 to 7 and then at each iteration we will scan binary representation (using masking
operation) of i and check leftmost n binary position for 0 or 1.
Code in C:
The function "get_powerset" returns an 2-d array of size (2^n) X n where each row contains one element of the power-set. As the length of each element of the power set is not constant so we have used # as terminator except the element that contains all the element of the set. For example if the set is {1,2,3} then this function will return the below 2-d array:
Suppose you want the power-set of 3 variables a,b,c. Then take 3 boolean variables and generate their all their possible combination. For 3 variables it will be:
+---------+---------+----------+---------+ |Index |pos-2 |pos-1 |pos-0 | +---------+---------+----------+---------+ | 0 | 0 | 0 | 0 | +---------+---------+----------+---------+ | 1 | 0 | 0 | 1 | +---------+---------+----------+---------+ | 2 | 0 | 1 | 0 | +---------+---------+----------+---------+ | 3 | 0 | 1 | 1 | +---------+---------+----------+---------+ | 4 | 1 | 0 | 0 | +---------+---------+----------+---------+ | 5 | 1 | 0 | 1 | +---------+---------+----------+---------+ | 6 | 1 | 1 | 0 | +---------+---------+----------+---------+ | 7 | 1 | 1 | 1 | +---------+---------+----------+---------+Now print 'a' when there is an 1 in pos-0 and 'b' when there is an 1 in pos-1 and 'c' when there is an 1 in pos-2 and all position is 0 means NULL set. Now for 3 element set {a,b,c} power-set will be :
{ {NULL}, [000: all positions are 0] {a}, [001: only pos-0 is 1 others are 0] {b}, [010: only pos-1 is 1 ] {a,b} [011: pos-0 and pos-1 is 1] {c}, [100: only pos-3 is 1] {a,c}, [101: pos-1 and pos-2 is 1] {b,c}, [110: pos-1 and pos-2 is 1] {a,b,c} [111: all positions are 1] }
Now the problem is how to generate these boolean variables combination. Here we can use bitwise operator. We only need right/left shift operator and the bitwise AND(&) operator for masking purpose. Actually we will iterate a loop from 0 to (2^n) where n is the number of elements in the set and then scanning n leftmost element of each loop count and check whether it is 1 or 0.
For 3 variables we will use a loop i:=0 to 7 and then at each iteration we will scan binary representation (using masking
operation) of i and check leftmost n binary position for 0 or 1.
Code in C:
/*It needs one command line argument which is the number of elements in the set*/ #include<stdio.h> #include<stdlib.h> #include<math.h> #include<string.h> char **get_powerset(char *ptr, int k) { int i, j, num_element, mask, l, val; char **power_set; num_element = pow(2, k); power_set = malloc(sizeof(char *) * (num_element)); for (i = 0; i < num_element; i++) { power_set[i] = malloc(sizeof(char) * k); memset(power_set[i], '#', (sizeof(char) * k)); } for (i = num_element - 1; i >= 0; i--) { l = 0; for (j = k - 1; j >= 0; j--) { mask = 1 << j; if (i & mask) power_set[i][l++] = ptr[j]; } } return power_set; } int main(int argc, char **argv) { int i, num_element, k, j, num_item; char **power_set, *ptr; num_item = atoi(argv[1]); ptr = malloc(sizeof(char) * num_item); for (i = 0; i < num_item; i++) { printf("Enter %d no. element:", i); scanf(" %c", &ptr[i]); } power_set = get_powerset(ptr, num_item); num_element = pow(2, num_item); printf("\nPower Set is==>\n\n"); for (i = 0; i < num_element; i++) { printf("{"); for (j = 0; (power_set[i][j] != '#') && (j < num_item); j++) { printf("%c,", power_set[i][j]); } if (i == 0 && (power_set[i][0] == '#')) printf("NULL,"); printf("\b}"); printf("\n"); } return 0; }Description:
The function "get_powerset" returns an 2-d array of size (2^n) X n where each row contains one element of the power-set. As the length of each element of the power set is not constant so we have used # as terminator except the element that contains all the element of the set. For example if the set is {1,2,3} then this function will return the below 2-d array:
+----+----+----+ |# | | | {NULL} +----+----+----+ | 1 | # | | {1} +----+----+----+ | 2 |# | | {2} +----+----+----+ | 2 | 1 | # | {2,1} +----+----+----+ | 3 | # | | {3} +----+----+----+ | 3 | 1 | # | {3,1} +----+----+----+ | 3 | 2 | # | {3,2} +----+----+----+ | 3 | 2 | 1 | {3,2,1} +----+----+----+One problem with this logic is that it is limited to the size of the memory allocated to the data-type of i.
No comments:
Post a Comment