#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _PatternGenParams
{
int *src;
int *flag;
int *list;
int *indexes;
int srcsize;
int len;
int count;
int all;
} PatternGenParams;
extern int PatternGenInitP(PatternGenParams *params, int srcsize, int len);
extern int PatternGenInitA(PatternGenParams *params, int size);
extern int PatternGenInitBySrc(PatternGenParams *params, const int *sortedsrc ,int srcsize, int len);
extern void PatternGenReset(PatternGenParams *params);
extern void PatternGenRelease(PatternGenParams *params);
extern int PatternGenAllPattern(PatternGenParams *params);
extern int PatternGenHasNext(PatternGenParams *params);
extern int PatternGenCount(PatternGenParams *params);
extern int PatternGenLength(PatternGenParams *params);
extern const int* PatternGenGet(PatternGenParams *params, int n);
extern const int* PatternGenNext(PatternGenParams *params);
static int PatternGenCheckParams(PatternGenParams *params);
static int PatternGenInitCommon(PatternGenParams *params, int srcsize, int len);
static int nCr(int n, int r);
static int nPr(int n, int r);
static int PatternGenCheckParams(PatternGenParams *params) {
return params == NULL
|| params->src == NULL
|| params->flag == NULL
|| params->list == NULL
|| params->indexes == NULL
|| params->count < 0
|| params->all < 0;
}
static int PatternGenInitCommon(PatternGenParams *params, int srcsize, int len) {
if (srcsize < 2 || len < 2 || srcsize < len || params == NULL) {
return 1;
}
params->srcsize = srcsize;
params->len = len;
params->count = 0;
params->all = 0;
params
->src
= (int*)calloc(params
->srcsize
, sizeof(int)); params
->flag
= (int*)calloc(params
->srcsize
, sizeof(int));
params
->indexes
= (int*)calloc(params
->len
, sizeof(int)); params
->list
= (int*)calloc(params
->len
, sizeof(int));
return 0;
}
extern int PatternGenInitP(PatternGenParams *params, int srcsize, int len) {
int i;
if (PatternGenInitCommon(params, srcsize, len)) {
return 1;
}
for (i = 0; i < params->srcsize; i++) {
params->src[i] = i + 1;
}
PatternGenReset(params);
return 0;
}
extern int PatternGenInitA(PatternGenParams *params, int size) {
return PatternGenInitP(params, size, size);
}
extern int PatternGenInitBySrc(PatternGenParams *params, const int *sortedsrc ,int srcsize, int len) {
if (PatternGenInitCommon(params, srcsize, len)) {
return 1;
}
memcpy(params
->src
, sortedsrc
, sizeof(int) * params
->srcsize
);
PatternGenReset(params);
return 0;
}
extern void PatternGenRelease(PatternGenParams *params) {
if (params == NULL) {
return;
}
if (params->src) {
params->src = NULL;
}
if (params->flag) {
params->flag = NULL;
}
if (params->list) {
params->list = NULL;
}
if (params->indexes) {
params->indexes = NULL;
}
params->count = params->all = 0;
}
extern void PatternGenReset(PatternGenParams *params) {
int i;
if (PatternGenCheckParams(params)) {
return;
}
for (i = 0; i < params->len; i++) {
params->flag[params->indexes[i]] = 0;
}
for (i = 0; i < params->len; i++) {
params->indexes[i] = i;
params->list[i] = params->src[params->indexes[i]];
params->flag[params->indexes[i]] = 1;
}
params->count = 0;
}
extern int PatternGenAllPattern(PatternGenParams *params) {
int i, c;
if (params->all == 0) {
params->all = nCr(params->srcsize, params->len)
* nPr(params->len, params->len);
c = 0;
for (i = 1; i < params->srcsize; i++) {
if (params->src[i - 1] == params->src[i]) {
c++;
} else {
if (c) {
c++;
params->all /= nPr(c, c);
c = 0;
}
}
}
if (c) {
params->all /= nPr(c, c);
}
}
return params->all;
}
extern const int* PatternGenGet(PatternGenParams *params, int n) {
if (PatternGenCheckParams(params)) {
return NULL;
}
if (n < 1 || n > PatternGenAllPattern(params)) {
return NULL;
}
while (n != params->count) {
PatternGenNext(params);
}
return params->list;
}
extern int PatternGenHasNext(PatternGenParams *params) {
int i;
if (PatternGenCheckParams(params)) {
return 0;
}
if (params->count == 0) {
return 1;
}
for (i = 0; i < params->len; i++) {
if (params->src[params->indexes[i]]
!= params->src[params->srcsize - i - 1]) {
return 1;
}
}
return 0;
}
const int* PatternGenNext(PatternGenParams *params) {
int i, j, b, f;
if (PatternGenCheckParams(params)) {
return NULL;
}
if (params->count == 0) {
params->count++;
return params->list;
}
i = params->len - 1;
params->flag[params->indexes[i]] = 0;
f = 1;
for (;;) {
if (f) {
b = params->src[params->indexes[i]];
for (j = params->indexes[i] + 1; j < params->srcsize; j++) {
if (params->flag[j] == 0 && params->src[j] != b) {
break;
}
}
} else {
for (j = 0; j < params->srcsize; j++) {
if (params->flag[j] == 0) {
break;
}
}
f = 1;
}
if (j == params->srcsize) {
i--;
if (i < 0) {
PatternGenReset(params);
break;
} else {
params->flag[params->indexes[i]] = 0;
}
} else {
params->indexes[i] = j;
params->list[i] = params->src[params->indexes[i]];
params->flag[params->indexes[i]] = 1;
i++;
if (i == params->len) {
// kakutei
break;
} else {
f = 0;
}
}
}
params->count++;
return params->list;
}
extern int PatternGenCount(PatternGenParams *params) {
if (PatternGenCheckParams(params)) {
return 0;
}
return params->count;
}
extern int PatternGenLength(PatternGenParams *params) {
if (PatternGenCheckParams(params)) {
return 0;
}
return params->len;
}
static int nCr(int n, int r) {
int i, c;
if (n < 0 || r < 0 || n < r) {
return 0;
}
if (n - r < r) {
r = n - r;
}
c = 1;
for (i = 1; i <= r; i++) {
c *= n;
c /= i;
n--;
}
return c;
}
static int nPr(int n, int r) {
int p;
if (n < 0 || r < 0 || n < r) {
return 0;
}
p = 1;
while (r > 0) {
p *= n;
n--;
r--;
}
return p;
}
int main(void) {
PatternGenParams params, params2, params3;
PatternGenParams *gen = ¶ms;
PatternGenParams *gen2 = ¶ms2;
PatternGenParams *gen3 = ¶ms3;
const int *k;
int i;
int src[] = { 1, 2, 2, 5};
int len = sizeof(src) / sizeof(src[0]);
PatternGenInitA(gen, 4);
PatternGenInitP(gen2, 5, 3);
PatternGenInitBySrc(gen3, src, len, len);
k = PatternGenGet(gen, 15);
printf("%08d: ", PatternGenCount
(gen
)); for (i = 0; i < PatternGenLength(gen); i++) {
putchar("_ABCDEFGHIJKLMNOPQRSTUVWXYZ"[k
[i
]]); }
PatternGenReset(gen);
printf("all pattern: %d\n", PatternGenAllPattern
(gen
));
while (PatternGenHasNext(gen)) {
k = PatternGenNext(gen);
printf("%08d: ", PatternGenCount
(gen
)); for (i = 0; i < PatternGenLength(gen); i++) {
putchar("_ABCDEFGHIJKLMNOPQRSTUVWXYZ"[k
[i
]]); }
}
printf("all pattern 2: %d\n", PatternGenAllPattern
(gen2
));
while (PatternGenHasNext(gen2)) {
k = PatternGenNext(gen2);
printf("%08d: ", PatternGenCount
(gen2
)); for (i = 0; i < PatternGenLength(gen2); i++) {
putchar("_ABCDEFGHIJKLMNOPQRSTUVWXYZ"[k
[i
]]); }
}
printf("all pattern 3: %d\n", PatternGenAllPattern
(gen3
));
while (PatternGenHasNext(gen3)) {
k = PatternGenNext(gen3);
printf("%08d: ", PatternGenCount
(gen3
)); for (i = 0; i < PatternGenLength(gen3); i++) {
}
}
PatternGenRelease(gen);
PatternGenRelease(gen2);
PatternGenRelease(gen3);
return 0;
}