This is not your typical mastermind question, I am not trying to find the right answer. Merely to check the answer and provide a result as fast as possible. The function signature cannot be changed, however the contents are just my best guess. Here's what I've come up with :
typedef int Code[100]; /* Arbitrary size */
void check_answer(
int code_length, /* Effective length of the code */
const Code answer, /* Answer to check */
const Code code, /* The actual code */
int *black, /* Returns count of right digits in right place */
int *white /* Returns count of right digits in wrong place */
) {
Code code_mask; /* Masks already-matched digits of the actual code */
Code answer_mask; /* Masks already-matched digits of the answer code */
int i, j;
*black = 0;
*white = 0;
/* Count black pegs */
for ( i = 0; i < code_length; i++ ) {
if ( answer[ i ] == code[ i ] ) {
*black += 1;
code_mask[ i ] = 1;
answer_mask[ i ] = 1;
} else {
code_mask[ i ] = 0;
answer_mask[ i ] = 0;
}
}
/* Count white pegs */
for ( i = 0; i < code_length; i++ ) {
if ( answer_mask[ i ] ) continue; /* Skip already matched */
for ( j = 0; j < code_length; j++ ) {
/*
Skip already-matched or same-index :
If mask is 0, same-index is necessarily different
*/
if ( code_mask[ j ] || i == j ) continue;
if ( answer[ i ] == code[ j ] ) {
*white += 1;
code_mask[ j ] = 1; /* Mask code only, previous answer_mask entries are never used again */
break; /* Answer digit is matched, skip to next */
}
}
}
}
Context : In this exercise, the solver algorithm uses this same function to check whether each potential next guess, were it to be the actual code, would produce the same answers for previously submitted guesses. Once it finds such a guess, it submits it to be tested against the real code.
The goal is to be as fast as possible with this algorithm structure, the check_answer
function being the critical hot-path. For a 12-color 9-digit code, it is called in the order of 10 billion times.
code_length
have? What is the maximum color? \$\endgroup\$unsigned char
arrays, no observable difference. \$\endgroup\$code_length
were limited to 64, that would (probably? I didn't work it out) allow a nice implementation of the white pegs based on bitmasks (no arrays, no searching) \$\endgroup\$SIMD
via bitwiseand
, although we'd still have to iterate through the resulting array to obtain the total, so I'm not certain if it would be faster. \$\endgroup\$