Under construction

Still being built. Things may change

Filtration

Time limit1sMemory limit128 MB

Summary
Parse a set of FIR filter equations, evaluate each filter's output stream in dependency order, and print the resulting samples.
Level

Hard8 of 10

Topics
Simulation, Implementation, Graph, Topological sort
Solved
No attempts yet

Problem

Digital signal processing (DSP) creates effects such as the "echo" often heard in music, or the modulation applied to certain singers' voices. These effects are produced with Finite Impulse Response (FIR) filters.

Consider an input stream of samples: a sequence of integers, each between 0 and 255 inclusive (the range of an 8-bit sample). The samples arrive one after another as the digital representation of a waveform. An FIR mixer combines several streams into one; an FIR echo filter turns one input into one output; and so on.

An FIR filter is written as an equation, with the input signals on one side and the output on the other. For example,

Y = X[0] + X[-5]

is a (post-)echo filter: sample ii of YY equals the value of XX at the same position plus the value of XX five samples earlier. In general, a reference X[k]X[k] used while producing output position ii reads X[i+k]X[i + k]; if i+ki + k falls outside the valid range 0…S−10 \dots S-1, that value is taken to be 0.

Every FIR equation obeys the following Backus-Naur Form (BNF) grammar:

EQUATION ::= STREAM __ "=" __ EXPR
STREAM   ::= a single upper-case letter naming a sample stream, such as A or X
EXPR     ::= VALUE | SAMPLE | EXPR __ OPER __ EXPR | "(" __ EXPR __ ")"
VALUE    ::= a floating-point number, such as 0.25, 5, or -1.5
SAMPLE   ::= STREAM "[" OFFSET "]"
OFFSET   ::= an integer sample offset, such as 0, 1, or -5, between -100 and 100 inclusive
OPER     ::= "*" | "+" | "-"

Operators follow the usual precedence (parentheses first, then multiplication, then addition and subtraction, otherwise left to right). Only after all of a filter's arithmetic is complete is the result rounded down (floored) to the nearest integer and then clamped to the range 0…2550 \dots 255; this clamped 8-bit value is the filter's output sample. The __ symbol denotes one or more spaces, and whitespace is allowed only where the grammar explicitly shows it.

For example, a simple low-pass filter can be written as

Z = 0.5 * Y[0] + 0.25 * Y[-1] + 0.25 * Y[1]

Each output of ZZ is based on the matching value of YY, adjusted by its nearest neighbours. A simple mixer can be written as

D = C[0] + B[0]

though such a filter can obviously clip.

For more complex effects, filters are chained together. Here every stream is either an input stream (for example, the source audio) or the output of a single FIR filter. A stream may be used as an input by more than one filter, forming a filter network.

Given a set of FIR filter definitions and starting inputs, output all of the filter outputs. No FIR filter uses more than 10 operators, more than ten pairs of parentheses, or more than 80 characters. Each data set has at least one input stream and at least one filter, and every stream referenced by a filter is defined in the same data set. All streams in a data set have the same number of samples, and the network has no feedback loops — no filter depends, directly or indirectly, on its own output.

(Although feedback loops sure sound cool when Pete Townshend uses them.)

Input

The first line contains a single integer DD (1≤D≤1001 \le D \le 100), the number of data sets. Each data set consists of:

  • A line with a single integer NN (2≤N≤262 \le N \le 26), the number of streams in the data set.
  • A line with a single integer SS (1≤S≤1001 \le S \le 100), the number of samples in every stream.
  • NN lines, each describing one stream. Stream names are distinct within a data set. Each line is one of:
    • an input stream, written STREAM % sam1 sam2 sam3 … samS, where STREAM is a single capital letter and sam1 … samS are its samples. The samples and the % marker are separated by whitespace.
    • an FIR filter, written STREAM = EXPR as described above.

Output

For each data set, print a header line DATA SET #k, where kk is 1 for the first data set, 2 for the second, and so on. Then, for every FIR filter in that data set (in alphabetical order by stream name), print its output stream on its own line in the form STREAM % sam1 sam2 sam3 … samS. Input streams are not printed.

Examples3

  1. Example 1

    Input
    3
    3
    5
    A % 10 20 30 20 10
    B = A[0] + A[-1]
    C = 0.5 * ( A[0] + B[0] )
    3
    5
    Z = 0.5 * Y[0] + 0.5 * B[0]
    Y % 50 10 50 10 50
    B % 10 50 10 50 15
    3
    5
    A % 1 2 3 4 5
    B = A[-2]
    C = B[2]
    
    Expected output
    DATA SET #1
    B % 10 30 50 50 30
    C % 10 25 40 35 20
    DATA SET #2
    Z % 30 30 30 30 32
    DATA SET #3
    B % 0 0 1 2 3
    C % 1 2 3 0 0
    
  2. Example 2

    Input
    1
    2
    8
    A % 100 200 250 255 0 100 200 50
    B = A[0] + A[-1]
    
    Expected output
    DATA SET #1
    B % 100 255 255 255 255 100 255 250
    
  3. Example 3

    Input
    1
    2
    6
    Y % 0 100 0 100 0 100
    Z = 0.5 * Y[0] + 0.25 * Y[-1] + 0.25 * Y[1]
    
    Expected output
    DATA SET #1
    Z % 25 50 50 50 50 50