new files

This commit is contained in:
Ingy döt Net 2013-04-10 12:38:42 -07:00
parent 3af7344581
commit 86c034bb8b
1364 changed files with 21352 additions and 0 deletions

View file

@ -0,0 +1,111 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#define DEBUG
void best_shuffle(const char* txt, char* result) {
const size_t len = strlen(txt);
if (len == 0)
return;
#ifdef DEBUG
// txt and result must have the same length
assert(len == strlen(result));
#endif
// how many of each character?
size_t counts[UCHAR_MAX];
memset(counts, '\0', UCHAR_MAX * sizeof(int));
size_t fmax = 0;
for (size_t i = 0; i < len; i++) {
counts[(unsigned char)txt[i]]++;
const size_t fnew = counts[(unsigned char)txt[i]];
if (fmax < fnew)
fmax = fnew;
}
assert(fmax > 0 && fmax <= len);
// all character positions, grouped by character
size_t *ndx1 = malloc(len * sizeof(size_t));
if (ndx1 == NULL)
exit(EXIT_FAILURE);
for (size_t ch = 0, i = 0; ch < UCHAR_MAX; ch++)
if (counts[ch])
for (size_t j = 0; j < len; j++)
if (ch == (unsigned char)txt[j]) {
ndx1[i] = j;
i++;
}
// regroup them for cycles
size_t *ndx2 = malloc(len * sizeof(size_t));
if (ndx2 == NULL)
exit(EXIT_FAILURE);
for (size_t i = 0, n = 0, m = 0; i < len; i++) {
ndx2[i] = ndx1[n];
n += fmax;
if (n >= len) {
m++;
n = m;
}
}
// how long can our cyclic groups be?
const size_t grp = 1 + (len - 1) / fmax;
assert(grp > 0 && grp <= len);
// how many of them are full length?
const size_t lng = 1 + (len - 1) % fmax;
assert(lng > 0 && lng <= len);
// rotate each group
for (size_t i = 0, j = 0; i < fmax; i++) {
const size_t first = ndx2[j];
const size_t glen = grp - (i < lng ? 0 : 1);
for (size_t k = 1; k < glen; k++)
ndx1[j + k - 1] = ndx2[j + k];
ndx1[j + glen - 1] = first;
j += glen;
}
// result is original permuted according to our cyclic groups
result[len] = '\0';
for (size_t i = 0; i < len; i++)
result[ndx2[i]] = txt[ndx1[i]];
free(ndx1);
free(ndx2);
}
void display(const char* txt1, const char* txt2) {
const size_t len = strlen(txt1);
assert(len == strlen(txt2));
int score = 0;
for (size_t i = 0; i < len; i++)
if (txt1[i] == txt2[i])
score++;
(void)printf("%s, %s, (%u)\n", txt1, txt2, score);
}
int main() {
const char* data[] = {"abracadabra", "seesaw", "elk", "grrrrrr",
"up", "a", "aabbbbaa", "", "xxxxx"};
const size_t data_len = sizeof(data) / sizeof(data[0]);
for (size_t i = 0; i < data_len; i++) {
const size_t shuf_len = strlen(data[i]) + 1;
char shuf[shuf_len];
#ifdef DEBUG
memset(shuf, 0xFF, sizeof shuf);
shuf[shuf_len - 1] = '\0';
#endif
best_shuffle(data[i], shuf);
display(data[i], shuf);
}
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,106 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct letter_group_t {
char c;
int count;
} *letter_p;
struct letter_group_t all_letters[26];
letter_p letters[26];
/* counts how many of each letter is in a string, used later
* to generate permutations
*/
int count_letters(const char *s)
{
int i, c;
for (i = 0; i < 26; i++) {
all_letters[i].count = 0;
all_letters[i].c = i + 'a';
}
while (*s != '\0') {
i = *(s++);
/* don't want to deal with bad inputs */
if (i < 'a' || i > 'z') {
fprintf(stderr, "Abort: Bad string %s\n", s);
exit(1);
}
all_letters[i - 'a'].count++;
}
for (i = 0, c = 0; i < 26; i++)
if (all_letters[i].count)
letters[c++] = all_letters + i;
return c;
}
int least_overlap, seq_no;
char out[100], orig[100], best[100];
void permutate(int n_letters, int pos, int overlap)
{
int i, ol;
if (pos < 0) {
/* if enabled will show all shuffles no worse than current best */
// printf("%s: %d\n", out, overlap);
/* if better than current best, replace it and reset counter */
if (overlap < least_overlap) {
least_overlap = overlap;
seq_no = 0;
}
/* the Nth best tie has 1/N chance of being kept, so all ties
* have equal chance of being selected even though we don't
* how many there are before hand
*/
if ( (double)rand() / (RAND_MAX + 1.0) * ++seq_no <= 1)
strcpy(best, out);
return;
}
/* standard "try take the letter; try take not" recursive method */
for (i = 0; i < n_letters; i++) {
if (!letters[i]->count) continue;
out[pos] = letters[i]->c;
letters[i]->count --;
ol = (letters[i]->c == orig[pos]) ? overlap + 1 : overlap;
/* but don't try options that's already worse than current best */
if (ol <= least_overlap)
permutate(n_letters, pos - 1, ol);
letters[i]->count ++;
}
return;
}
void do_string(const char *str)
{
least_overlap = strlen(str);
strcpy(orig, str);
seq_no = 0;
out[least_overlap] = '\0';
least_overlap ++;
permutate(count_letters(str), least_overlap - 2, 0);
printf("%s -> %s, overlap %d\n", str, best, least_overlap);
}
int main()
{
srand(time(0));
do_string("abracadebra");
do_string("grrrrrr");
do_string("elk");
do_string("seesaw");
do_string("");
return 0;
}

View file

@ -0,0 +1,5 @@
abracadebra -> edbcarabaar, overlap 0
grrrrrr -> rrgrrrr, overlap 5
elk -> kel, overlap 0
seesaw -> ewsesa, overlap 0
-> , overlap 0

View file

@ -0,0 +1,36 @@
#include <stdio.h>
#include <string.h>
#define FOR(x, y) for(x = 0; x < y; x++)
char *best_shuffle(const char *s, int *diff)
{
int i, j = 0, max = 0, l = strlen(s), cnt[128] = {0};
char buf[256] = {0}, *r;
FOR(i, l) if (++cnt[(int)s[i]] > max) max = cnt[(int)s[i]];
FOR(i, 128) while (cnt[i]--) buf[j++] = i;
r = strdup(s);
FOR(i, l) FOR(j, l)
if (r[i] == buf[j]) {
r[i] = buf[(j + max) % l] & ~128;
buf[j] |= 128;
break;
}
*diff = 0;
FOR(i, l) *diff += r[i] == s[i];
return r;
}
int main()
{
int i, d;
const char *r, *t[] = {"abracadabra", "seesaw", "elk", "grrrrrr", "up", "a", 0};
for (i = 0; t[i]; i++) {
r = best_shuffle(t[i], &d);
printf("%s %s (%d)\n", t[i], r, d);
}
return 0;
}