Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
111
Task/Best-shuffle/C/best-shuffle-1.c
Normal file
111
Task/Best-shuffle/C/best-shuffle-1.c
Normal 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;
|
||||
}
|
||||
106
Task/Best-shuffle/C/best-shuffle-2.c
Normal file
106
Task/Best-shuffle/C/best-shuffle-2.c
Normal 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;
|
||||
}
|
||||
5
Task/Best-shuffle/C/best-shuffle-3.c
Normal file
5
Task/Best-shuffle/C/best-shuffle-3.c
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
abracadebra -> edbcarabaar, overlap 0
|
||||
grrrrrr -> rrgrrrr, overlap 5
|
||||
elk -> kel, overlap 0
|
||||
seesaw -> ewsesa, overlap 0
|
||||
-> , overlap 0
|
||||
36
Task/Best-shuffle/C/best-shuffle-4.c
Normal file
36
Task/Best-shuffle/C/best-shuffle-4.c
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue