#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

using namespace std;

/* SANITY CHECK: assertion macro for verifying input data and internal state */
#define ASSERT(e) { if(!(e)) { cerr << #e << endl; throw; } }

/* An stream is an ordered list of floating point samples */
typedef vector<double> stream_t;

/* A filter network consists of named filter equations */
typedef map<char, string> filterset_t;

/* A collection of named input and output streams */
typedef map<char, stream_t> streamset_t;

/*
 * Function prototypes for the recursive descent parser. The first argument is
 * a string buffer holding part of the equation still remaining to be parsed.
 * The other arguments are the samples and filter definitions as read in from
 * the input (or previously computed). Each of these functions returns a new
 * sample stream corresponding to the non-terminal symbol handled by the
 * function.
 */
stream_t parse_sum(istringstream &, streamset_t &, filterset_t &, int);
stream_t parse_term(istringstream &, streamset_t &, filterset_t &, int);
stream_t parse_expr(istringstream &, streamset_t &, filterset_t &, int);

/* Insertion operator prints out the individual samples in a stream */
ostream &operator<<(ostream &sout, stream_t const &data)
{
    for(int i = 0; i < data.size(); i++) {
        sout << " " << (int) data[i];
    }
    
    return sout;
}

/* Adding two streams together adds the individual samples */
stream_t &operator+=(stream_t &a, stream_t const &b)
{
    transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());
    return a;
}

/* Subtracting two streams subtracts the individual samples */
stream_t &operator-=(stream_t &a, stream_t const &b)
{
    transform(a.begin(), a.end(), b.begin(), a.begin(), minus<double>());
    return a;
}

/* Multiplying two streams together multiplies the individual samples */
stream_t &operator*=(stream_t &a, stream_t const &b)
{
    transform(a.begin(), a.end(), b.begin(), a.begin(), multiplies<double>());
    return a;
}

/*
 * Return a new stream that is time-shifted by the specified offset. A positive
 * offset (i.e. forward in time) shifts the stream to the left with trailing
 * zeroes at the end. A negative offset (i.e. backward in time) shifts
 * the stream to the right with leading zeroes at the beginning. If the
 * absolute value of offset is larger than the number of available samples,
 * then the output vector will contain all zeroes.
 */
stream_t shift(stream_t const &in, int offset)
{
    /* Initialize output vector with all zeroes */
    stream_t out(in.size(), 0);
    
    /* Iterators which define the range copied from "in" stream to "out" */
    stream_t::iterator outbegin = out.begin();
    stream_t::const_iterator inbegin = in.begin();
    stream_t::const_iterator inend = in.end();
    
    /* A positive (forward in time) offset gives trailing zeroes in "out" */
    if(offset >= 0) {
        inbegin += offset;
    }
    
    /* A negative (bacward in time) offset gives leading zeroes in "out" */
    else {
        outbegin += -offset;
        inend -= -offset;
    }

    /* If the offset it too large or too small, output will have all zeroes */
    if(inbegin < inend) {
        copy(inbegin, inend,outbegin);
    }
    
    return out;
}

/*
 * If the samples for stream "name" have not already been computed and stored
 * in "streams", then compute them by parsing the appropriate equation in
 * "filters". This function uses a recursive descent parser to recognize the
 * filter equation grammer. The original grammar has to be slightly rewritten
 * to remove the ambigiuity associated with operator precedence. Below is
 * the modified grammar in Extended Backus-Naur Form (the __ symbol is left
 * out for clarity):
 *
 * EQUATION ::= STREAM "=" SUM
 * SUM      ::= TERM { SUMOPER TERM }*
 * TERM     ::= EXPR { MULOPER EXPR }*
 * EXPR     ::= VALUE | SAMPLE | "(" SUM ")"
 * SUMOPER  ::= "+" | "-"
 * MULOPER  ::= "*"
 */
void compute(char name, streamset_t &streams, filterset_t &filters,
    int sample_num)
{
    /* SANITY CHECK: Detect undefined stream names */
    ASSERT(streams.find(name) != streams.end() || filters.find(name) !=
        filters.end())

    /* SANITY CHECK: Detect feedback loops */
    ASSERT(streams.find(name) == streams.end() || streams[name].size());

    /* Do nothing if this stream has been already computed */
    if(streams[name].size()) {
        return;
    }
    
    /* Parse this filter equation and compute its sample stream */
    istringstream text(filters[name]);
    stream_t value = parse_sum(text, streams, filters, sample_num);
    ASSERT(text.eof());
    
    /* Round and clip the output samples to integers in the [0,255] range */
    ASSERT(value.size() == sample_num);
    for(int i = 0; i < sample_num; i++) {
        int integer = (int) value[i];
        
        if(integer < 0) {
            value[i] = 0;
        }
        else if(integer > 255) {
            value[i] = 255;
        }
        else {
            value[i] = integer;
        }
    }

    /* Assign the computed stream to the stream set */
    streams[name] = value;
}

/* Parse SUM ::= TERM { SUMOPER TERM }* */
stream_t parse_sum(istringstream &text, streamset_t &streams,
    filterset_t &filters, int sample_num)
{
    /* The left hand side expression must always be present */
    stream_t result = parse_term(text, streams, filters, sample_num);

    /* Look ahead one token into the input stream */
    char oper;
    text >> oper;
    
    /* Keep parsing as long as any "+" or "-" operators exist */
    while(!text.eof()) {
        ASSERT(!text.fail());
 
        /* Add or subtract the right hand side expression */
        if(oper == '+') {
            result += parse_term(text, streams, filters, sample_num);
        }
        else if(oper == '-') {
            result -= parse_term(text, streams, filters, sample_num);
        }

        /* Otherwise this is the end of the SUM non-terminal */
        else {
            text.putback(oper);            
            break;
        }

        /* Look ahead one token into the input stream */
        text >> oper;        
    }

    return result;
}

/* Parse TERM ::= EXPR { MULOPER EXPR }* */
stream_t parse_term(istringstream &text, streamset_t &streams,
    filterset_t &filters, int sample_num)
{
    /* The left hand side expression must always be present */
    stream_t result = parse_expr(text, streams, filters, sample_num);
    
    /* Look ahead one token into the input stream */
    char oper;
    text >> oper;

    /* Keep parsing as long as any "*" operators exist */
    while(!text.eof()) {
        ASSERT(!text.fail());

        /* Multiply the result by the right hand side expression */
        if(oper == '*') {
            result *= parse_expr(text, streams, filters, sample_num);
        }

        /* Otherwise this is the end of the TERM non-terminal */
        else {
            text.putback(oper);
            break;
        }

        /* Look ahead one token into the input stream */
        text >> oper;
    }
   
    return result;
}

/* Parse EXPR ::= VALUE | SAMPLE | "(" SUM ")" */
stream_t parse_expr(istringstream &text, streamset_t &streams,
    filterset_t &filters, int sample_num)
{
    stream_t result;

    /* Extract the next token from the input stream */
    string token;
    text >> token;
    ASSERT(!text.fail());
   
    /* An opening parenthesis signals the start of a nested sub expression */
    if(token == "(") {
        result = parse_sum(text, streams, filters, sample_num);

        /* Match the closing parenthesis */
        char oper;        
        text >> oper;        
        ASSERT(!text.fail());
        ASSERT(oper == ')');
    }
    
    /* An uppercase letter signals a sample definition of the form "X[N]" */
    else if(isupper(token[0])) {
        istringstream str(token);
        char name, dummy1, dummy2;
        int offset;
        
        str >> name >> dummy1 >> offset >> dummy2;
        ASSERT(dummy1 == '[' && dummy2 == ']');
        ASSERT(offset >= -100 && offset <= 100);
        ASSERT(!str.fail() && !(str >> dummy1));

        /* Ensure the requested input stream has been calculated already */
        compute(name, streams, filters, sample_num);

        /* Return a time-shifted version of the requested input stream */
        result = shift(streams[name], offset);
    }
    
    /* Otherwise this token must be a floating point constant */
    else {
        istringstream str(token);
        double value;
        char dummy;
        
        str >> value;
        ASSERT(!str.fail() && !(str >> dummy));

        /* Return a sample stream initialized to the floating point constant */
        result = stream_t(sample_num, value);
    }
    
    return result;
}

/* Main body of program */
void process(void)
{
    int data_num, data_idx;
    
    /* Read how many data sets to process */
    cin >> data_num;
    
    /* Process each data set separately */
    for(data_idx = 0; data_idx < data_num; data_idx++) {
        int sample_num, input_num, input_idx;
        streamset_t streams;
        filterset_t filters;
        
        /* Read in the number of streams and samples */
        cin >> input_num >> sample_num;
        
        /* Read in each of the stream definitions */
        for(input_idx = 0; input_idx < input_num; input_idx++) {
            char name, oper;
            int sample_idx;
            
            /* Read in the stream name and % or = operator */
            cin >> name >> oper;
            ASSERT(name >= 'A' && name <= 'Z');
            ASSERT(oper == '%' || oper == '=');

            /* SANITY CHECK: Check for duplicate stream definitions */
            ASSERT(filters.find(name) == filters.end());
            ASSERT(streams.find(name) == streams.end());
            
            /* A % operator is an input stream */
            if(oper == '%') {
                for(sample_idx = 0; sample_idx < sample_num; sample_idx++) {
                    int sample;
                                
                    cin >> sample;
                    ASSERT(sample >= 0 && sample <= 255);
                    
                    streams[name].push_back(sample);
                }
            }
            
            /* A = operator is a filter definition */
            else {
                string filter;                
                getline(cin, filter);
                filters[name] = filter;
            }
        }

        /* SANITY CHECK: Need at least one input and output stream */
        ASSERT(filters.size() && streams.size());

        cout << "DATA SET #" << data_idx + 1 << endl;
        
        /*
         * Compute and print out the samples in each output stream. The STL map
         * in filterset_t guarantees the filter names are already sorted in
         * alphabetical order.
         */
        filterset_t::iterator i;
        for(i = filters.begin(); i != filters.end(); ++i) {
            compute(i->first, streams, filters, sample_num);
            cout << i->first << " %" << streams[i->first] << endl;
        }
    }
}

/* Run program and print out any exceptions that occur */
int main(void)
{
    /* Throw exceptions on failed data extraction in >> operator */
    cin.exceptions(ios::failbit);
    
    /* Run main body of code */
    try {
        process();
    }
    
    /* Catch unexpected EOF or bad input data */
    catch(ios::failure const &e) {
        cerr << "Unexpected EOF or data type mismatch on input" << endl;
    }

    return 0;
}