#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
/* type values used in init_char_set() function */
#define UPPER 1
#define LOWER 2
#define NUM 4
#define PUNCT 16
#define ALPHA 3
#define ALNUM 7
#define ALL 23
#define CUSTOM 32
/* pre defined char sets used in init_char_set() function */
#define UPPER_CHAR_SET "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define LOWER_CHAR_SET "abcdefghijklmnopqrstuvwxyz"
#define DIGIT_CHAR_SET "0123456789"
#define PUNCT_CHAR_SET "~!@#$%^&*()_+{}|[]:\"<>?,./;'\\=-"
#define MAX_CHARS 150
#define MAX_GUESS 20
#ifndef NUL
#define NUL '\0'
#endif
/* Function Prototypes */
void permute_rep (const char *set, int n, int r);
char *init_char_set (short int type, char *custom);
int *init_perm_array (int len);
char *make_perm_string (int *perm, const char *set, int len, int print_flag);
/* Main Function, Drives the permute_rep() function */
int
main (void)
{
char *set = NULL, custom[MAX_CHARS];
int r;
printf ("\nr-Permutation with repetitions.\n");
printf ("Enter String Set To Permute: ");
scanf ("%s", custom);
printf ("\nLength Of Permutations (r): ");
scanf ("%d", &r);
set = init_char_set (CUSTOM, custom);
printf ("\nPermutation Symbol set: \"%s\"\n", set);
permute_rep (set, strlen (set), r);
printf ("\nfinished\n");
return 0;
}
/* Function Name : permute_rep
* Parameters :
* @ (const char *) set : Pointer to the symbol sets to permute
* @ (int) n : The length upto which the set would be used
* @ (int) r : The length of the generated permutations
* Return Value : (void)
* Description : Generates all the Permutation with repetitions of length 'r' from the 'set' upto length 'n' .
* Prints them in stdout.
*/
void
permute_rep (const char *set, int n, int r)
{
int *perm;
int i, j;
perm = init_perm_array (r);
while (perm[r] == 0)
{
for (j = 0; j < n; j++)
{
make_perm_string (perm, set, r, 1);
perm[0]++;
}
perm[0]++;
for (i = 0; i < r; i++)
{
if (perm[i] >= n)
{
perm[i] = 0;
perm[i + 1]++;
}
}
}
}
/* Function Name : init_char_set
* Parameters :
* @ (short int) type : The inbuilt type values to select character sets.
* 'type' could be:
* 1, 2, 4, 16, 32 or any of these values ORed. These are #defined
* @ (char *) custom : Pointer to a custom symbol set to initialize. type should be 32 in,
* else this pointer is ignored.
* Return Value : (char *) : Returns a pointer to the initialized character set
* Description : Allocates and initializes a pointer with a string of symbols to be permuted, and returns it
*/
char *
init_char_set (short int type, char *custom)
{
char upper[] = UPPER_CHAR_SET;
char lower[] = LOWER_CHAR_SET;
char num[] = DIGIT_CHAR_SET;
char punct[] = PUNCT_CHAR_SET;
char *set;
set = (char *) malloc (sizeof (char) * MAX_CHARS);
if (type & UPPER)
{
strcat (set, upper);
}
if (type & LOWER)
{
strcat (set, lower);
}
if (type & NUM)
{
strcat (set, num);
}
if (type & PUNCT)
{
strcat (set, punct);
}
/* Remove redundant elements from custom string and build set. If input set is "hello"
* then it will be reduced to "helo"
*/
if (type & CUSTOM)
{
int i, j, k, n = strlen (custom), flag;
for (i = 0, k = 0; i < n; i++)
{
for (flag = 0, j = 0; j < k; j++)
{
if (custom[i] == set[j])
{
flag = 1;
break;
}
}
if (flag == 0)
{
set[k] = custom[i];
k++;
}
}
}
return set;
}
/* Function Name : init_perm_array
* Parameters :
* @ (int) len : The length of the array
* Return Value : (int *) : A pointer to the allocated permutation array
* Description : Allocates and initializes with 0 an array, which is used for generating 'r' base numbers
*/
int *
init_perm_array (int len)
{
int *perm;
perm = (int *) calloc (len + 1, sizeof (int));
return perm;
}
/* Function Name : make_perm_string
* Parameters :
* @ (int *) perm : Pointer to the current permutation count state
* @ (const char *) set : Pointer to the symbol set to be permuted
* @ (int) len : The length of permutation
* @ (int) print_state : A flag. If true prints the permutation in stdout, else does not.
* Return Value : (char *) : A pointer to the string representing the permutation
* Description : Returns a pointer to a string representing the permutation of the symbols
* from the 'set' represented by 'perm' state. This simply labels each position count of 'perm'
* with the symbols from 'set' makes a string and returns it.
* It also prints the string if 'print_state' is true.
*/
char *
make_perm_string (int *perm, const char *set, int len, int print_state)
{
char *perm_str;
int i, j;
perm_str = (char *) malloc (sizeof (char) * (len + 1));
for (i = len - 1, j = 0; i >= 0; i--, j++)
{
perm_str[j] = set[*(perm + i)];
}
perm_str[j] = NUL;
if (print_state)
printf ("%s\n", perm_str);
return perm_str;
}