/* Given a set of consecutive characters, find a hash expression that would produce the desired symbols. Result: ('A' ^ 91) * 22 % 54 = ' ' ('B' ^ 91) * 22 % 54 = '\n' ('C' ^ 91) * 22 % 54 = '*' ('D' ^ 91) * 22 % 54 = '"' */ #include /* List of consecutive unused characters from prime_cut2.c */ static const char *kKeySets[3] = { "5678", "ABCD", "wxyz", }; /* Hash function. */ static int Hash(char input, int p, int q, int r) { return (input ^ r) * p % q; } /* Try hashing a set of keys to the desired symbols. */ static void TryKeySet(const char *keys) { int p, q, r, v, coverage; const char *k; for(p = 0; p < 1000; p++) { for(q = 1; q < 1000; q++) { for(r = 0; r < 256; r++) { coverage = 0; for(k = keys; *k; k++) { v = Hash(*k, p, q, r); if( v == ' ' ) coverage |= 1; if( v == '\n' ) coverage |= 2; if( v == '"' ) coverage |= 4; if( v == '*' ) coverage |= 8; } if( coverage == 15 ) { printf("keys = %s, p = %d, q = %d, r = %d:", keys, p, q, r); for(k = keys; *k; k++) printf("\t%d->%d", *k, Hash(*k, p, q, r)); putchar('\n'); } } } } } int main(void) { int k; for(k = 0; k < 3; k++) TryKeySet(kKeySets[k]); return 0; }