// Arup Guha
// 9/14/2015
// Solution to 2015 Fall COP 3502 Program #3: Mastermind
/*** Edited to be Spring 2017 Quiz #1 Question 3 Solution ***/

#include <stdio.h>
#include <stdlib.h>

int numPerfectMatches(int* board, int* answer);
int* solve(int* combo, int k);
int eval(int* combo);
int numWrongMatches(int* board, int* answer);
int totalMatches(int* board, int* answer);
int* getColorChart(int* board);
int sumMatches(int* colors1, int* colors2);
int min(int a, int b);
void print(int* arr, int len);

// Making these global so our recursive function isn't over-burdened with variables.
int numSlots, numColors, numMoves;
int** guesses;
int* correct;
int* incorrect;

int main() {

    int loop, numCases;
    scanf("%d", &numCases);

    // Process each case.
    for (loop=0; loop<numCases; loop++) {

        int i, j;
        scanf("%d%d%d", &numSlots, &numColors, &numMoves);

        // Make space for guess table and results of guesses.
        guesses = calloc(numMoves, sizeof(int*));
        correct = calloc(numMoves, sizeof(int));
        incorrect = calloc(numMoves, sizeof(int));

        for (i=0; i<numMoves; i++)
            guesses[i] = calloc(numSlots, sizeof(int));

        // Read in all guess data here.
        for (i=0; i<numMoves; i++) {
            for (j=0; j<numSlots; j++)
                scanf("%d", &guesses[i][j]);
            scanf("%d%d", &correct[i], &incorrect[i]);
        }

        // Store combo we're filling in here.
        int* combo = calloc(numSlots, sizeof(int));

        // Make initial recursive call and print solution.
        int* firstsol = solve(combo, 0);
        print(firstsol, numSlots);

        // Memory clean up.
        for (i=0; i<numMoves; i++)
            free(guesses[i]);
        free(guesses);
        free(correct);
        free(incorrect);
        free(combo);
        free(firstsol);
    }

    return 0;
}

/*** Quiz Solution
  Returns the first possible lexicographical solution to the mastermind puzzle.
***/
int* solve(int* combo, int k) {

    int i;

    // Base case - all slots filled in.
    if (k == numSlots) {
        int res = eval(combo);

        // No solution.
        if (res == 0)
            return NULL ;

        // Got a solution - copy it and return.
        else {
            int* array = malloc(numSlots*sizeof(int)) ;
            for (i=0; i<numSlots; i++)
                array[i] = combo[i] ;
            return array;
        }

    }

    // Try each color in slot k.
    for (i=0; i<numColors; i++) {
        combo[k] = i;
        int* arr = solve(combo, k+1);

        // This branch yielded a solution - just return it.
        if (arr != NULL)
            return arr;
    }

    // If we make it here, no solution was found.
    return NULL;
}

// Returns 1 iff combo is consistent with given information, 0 otherwise.
int eval(int* combo) {

    int i;

    // Look at each guess.
    for (i=0; i<numMoves; i++) {

        // Get the matches between the guess and this combo.
        int correctMatches = numPerfectMatches(guesses[i], combo);
        int incorrectMatches = numWrongMatches(guesses[i], combo);

        // If the results aren't identical to what was given, it couldn't have been this combo!
        if (correctMatches != correct[i] || incorrectMatches != incorrect[i])
            return 0;
    }

    // If we get here, we're good!
    return 1;
}

// Returns the number of perfect matches between board and answer.
int numPerfectMatches(int* board, int* answer) {

    int i;
    int numMatches = 0;

    // Go through each slot once, seeing if corresponding slots match.
    for (i=0; i<numSlots; i++)
        if (board[i] == answer[i])
            numMatches++;

    // Return the correct number of matches.
    return numMatches;
}

// A wrapper function to make the code easier to read.
int numWrongMatches(int* board, int* answer) {
    return totalMatches(board, answer) - numPerfectMatches(board, answer);
}

// Returns the number of total matches, correct and incorrect between board and answer.
int totalMatches(int* board, int* answer) {

    // Get frequencies of both boards.
    int* boardColors = getColorChart(board);
    int* answerColors = getColorChart(answer);

    // Solve, free memory and return answer.
    int res = sumMatches(boardColors, answerColors);
    free(boardColors);
    free(answerColors);
    return res;
}

// Returns a frequency chart of each color on board.
int* getColorChart(int* board) {

    int i;
    int* colors = calloc(numColors, sizeof(int));
    for (i=0; i<numSlots; i++)
        colors[board[i]]++;
    return colors;
}

// Return the total number of matches between color frequencies colors1 and colors2.
int sumMatches(int* colors1, int* colors2) {

    int sum = 0, i;

    // For each color, the minimum between the two combos is what we want to count.
    for (i=0; i<numColors; i++)
        sum += min(colors1[i], colors2[i]);
    return sum;
}

// Returns the minimum of a and b.
int min(int a, int b) {
    return a < b ? a : b;
}

// Prints arr[0..len-1].
void print(int* arr, int len) {
    int i;
    for (i=0; i<len-1; i++)
        printf("%d ", arr[i]);
    printf("%d\n", arr[len-1]);
}
