Best shuffle: Difference between revisions
Content added Content deleted
(→{{header|Ursala}}: Omit bc, dc.) |
(Removed some casts from C version) |
||
Line 126: | Line 126: | ||
#define DEBUG |
#define DEBUG |
||
void best_shuffle(const |
void best_shuffle(const char* txt, char* result) { |
||
const |
const size_t len = strlen(txt); |
||
if (len == 0) |
if (len == 0) |
||
return; |
return; |
||
Line 133: | Line 133: | ||
#ifdef DEBUG |
#ifdef DEBUG |
||
// txt and result must have the same length |
// txt and result must have the same length |
||
assert(len == |
assert(len == strlen(result)); |
||
#endif |
#endif |
||
// how many of each character? |
// how many of each character? |
||
size_t counts[UCHAR_MAX]; |
|||
memset(counts, '\0', UCHAR_MAX * sizeof(int)); |
memset(counts, '\0', UCHAR_MAX * sizeof(int)); |
||
size_t fmax = 0; |
|||
for ( |
for (size_t i = 0; i < len; i++) { |
||
counts[txt[i]]++; |
counts[(unsigned char)txt[i]]++; |
||
const |
const size_t fnew = counts[(unsigned char)txt[i]]; |
||
if (fmax < fnew) |
if (fmax < fnew) |
||
fmax = fnew; |
fmax = fnew; |
||
} |
} |
||
assert(fmax > 0 && fmax <= len); |
assert(fmax > 0 && fmax <= len); |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
// all character positions, grouped by character |
// all character positions, grouped by character |
||
size_t *ndx1 = malloc(len * sizeof(size_t)); |
|||
if (ndx1 == NULL) |
if (ndx1 == NULL) |
||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||
for ( |
for (size_t ch = 0, i = 0; ch < UCHAR_MAX; ch++) |
||
if (counts[ch]) |
if (counts[ch]) |
||
for ( |
for (size_t j = 0; j < len; j++) |
||
if (ch == txt[j]) { |
if (ch == (unsigned char)txt[j]) { |
||
ndx1[i] = j; |
ndx1[i] = j; |
||
i++; |
i++; |
||
Line 167: | Line 161: | ||
// regroup them for cycles |
// regroup them for cycles |
||
size_t *ndx2 = malloc(len * sizeof(size_t)); |
|||
if (ndx2 == NULL) |
if (ndx2 == NULL) |
||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||
for ( |
for (size_t i = 0, n = 0, m = 0; i < len; i++) { |
||
ndx2[i] = ndx1[n]; |
ndx2[i] = ndx1[n]; |
||
n += fmax; |
n += fmax; |
||
Line 178: | Line 172: | ||
} |
} |
||
} |
} |
||
⚫ | |||
⚫ | |||
assert(grp > 0 && grp <= len); |
|||
⚫ | |||
⚫ | |||
assert(lng > 0 && lng <= len); |
|||
// rotate each group |
// rotate each group |
||
for ( |
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 ( |
for (size_t k = 1; k < glen; k++) |
||
ndx1[j + k - 1] = ndx2[j + k]; |
ndx1[j + k - 1] = ndx2[j + k]; |
||
ndx1[j + glen - 1] = first; |
ndx1[j + glen - 1] = first; |
||
Line 191: | Line 193: | ||
// result is original permuted according to our cyclic groups |
// result is original permuted according to our cyclic groups |
||
result[len] = '\0'; |
result[len] = '\0'; |
||
for ( |
for (size_t i = 0; i < len; i++) |
||
result[ndx2[i]] = txt[ndx1[i]]; |
result[ndx2[i]] = txt[ndx1[i]]; |
||
Line 198: | Line 200: | ||
} |
} |
||
void display(char* txt1, char* txt2) { |
void display(const char* txt1, const char* txt2) { |
||
const size_t len = strlen(txt1); |
|||
assert(len == |
assert(len == strlen(txt2)); |
||
int score = 0; |
int score = 0; |
||
for ( |
for (size_t i = 0; i < len; i++) |
||
if (txt1[i] == txt2[i]) |
if (txt1[i] == txt2[i]) |
||
score++; |
score++; |
||
(void)printf("%s, %s, (% |
(void)printf("%s, %s, (%u)\n", txt1, txt2, score); |
||
} |
} |
||
Line 211: | Line 213: | ||
char* data[] = {"abracadabra", "seesaw", "elk", "grrrrrr", |
char* data[] = {"abracadabra", "seesaw", "elk", "grrrrrr", |
||
"up", "a", "aabbbbaa", "", "xxxxx"}; |
"up", "a", "aabbbbaa", "", "xxxxx"}; |
||
const |
const size_t data_len = sizeof(data) / sizeof(data[0]); |
||
for ( |
for (size_t i = 0; i < data_len; i++) { |
||
const |
const size_t shuf_len = strlen(data[i]) + 1; |
||
char shuf[shuf_len]; |
|||
#ifdef DEBUG |
#ifdef DEBUG |
||
memset(shuf, 0xFF, shuf_len * sizeof( |
memset(shuf, 0xFF, shuf_len * sizeof(char)); |
||
shuf[shuf_len - 1] = '\0'; |
shuf[shuf_len - 1] = '\0'; |
||
#endif |
#endif |
||
best_shuffle( |
best_shuffle(data[i], shuf); |
||
display(data[i], |
display(data[i], shuf); |
||
} |
} |
||