Problem:
Problem J:
Matrix Calculator
Dr. Jimbo, an applied mathematician, needs to calculate matrices all day for solving his own problems. In his laboratory, he uses an excellent application program for manipulating matrix expressions, however, he cannot use it outside his laboratory because the software consumes much of resources. He wants to manipulate matrices outside, so he needs a small program similar to the excellent application for his handheld computer.
Your job is to provide him a program that computes expressions of matrices.
Expressions of matrices are described in a simple language. Its syntax is shown in Table J.1. Note that even a space and a newline have meaningful roles in the syntax.
The start symbol of this syntax is program that is defined as a sequence of assignments in Table J.1. Each assignment has a variable on the left hand side of an equal symbol ("
=
") and an expression of matrices on the right hand side followed by a period and a newline (
NL
). It denotes an assignment of the value of the expression to the variable. The variable (var in Table J.1) is indicated by an uppercase Roman letter. The value of the expression (
expr
) is a matrix or a scalar, whose elements are integers. Here, a scalar integer and a 1 × 1 matrix whose only element is the same integer can be used interchangeably.
An expression is one or more terms connected by "
+
" or "
-
" symbols. A term is one or more factors connected by "
*
" symbol. These operators ("
+
", "
-
", "
*
") are left associative.
A factor is either a primary expression (primary) or a "
-
" symbol followed by a factor. This unary operator "
-
" is right associative.
The meaning of operators are the same as those in the ordinary arithmetic on matrices: Denoting matrices by
A
and
B
,
A
+
B
,
A
-
B
,
A
*
B
, and -A are defined as the matrix sum, difference, product, and negation. The sizes of
A
and
B
should be the same for addition and subtraction. The number of columns of
A
and the number of rows of
B
should be the same for multiplication.
Note that all the operators +, -, * and unary - represent computations of addition, subtraction, multiplication and negation modulo
M
= 2
15
= 32768, respectively. Thus all the values are nonnegative integers between 0 and 32767, inclusive. For example, the result of an expression 2 - 3 should be 32767, instead of -1.
inum
is a non-negative decimal integer less than
M
.
var
represents the matrix that is assigned to the variable var in the most recent preceding assignment statement of the same variable.
matrix
represents a mathematical matrix similar to a 2-dimensional array whose elements are integers. It is denoted by a
row-seq
with a pair of enclosing square brackets.
row-seq
represents a sequence of rows, adjacent two of which are separated by a semicolon. row represents a sequence of expressions, adjacent two of which are separated by a space character.
For example,
[1 2 3;4 5 6]
represents a matrix
. The first row has three integers separated b
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int MOD = 32768;
typedef vector<int> List;
typedef vector<vector<int>> Matrix;
Matrix variables[26];

Matrix parseExpr(const char*& p);

void skip(const char *&p)
{
    while ( p && *p == ' ' ) p++;
}
bool consume(const char *&p, char c)
{
    if ( *p && *p == c )
    {
        p++;
        return true;
    }
    return false;
}
Matrix operator +(const Matrix &A, const Matrix &B)
{
    int H = A.size(), W = A[0].size();
    Matrix ret(H, List(W));
    for ( int y = 0 ; y < H ; y++ )
        for ( int x = 0 ; x < W ; x++ )
            ret[y][x] = (A[y][x] + B[y][x]) % MOD;
    return ret;
}
Matrix operator *(const Matrix &A, const Matrix &B)
{
    int Ha = A.size(), Wa = A[0].size();
    int Hb = B.size(), Wb = B[0].size();

    if ( Ha == 1 && Wa == 1 )
    {
        Matrix ret(Hb, List(Wb));
        for ( int y = 0 ; y < Hb ; y++ )
            for ( int x = 0 ; x < Wb ; x++ )
                ret[y][x] = (A[0][0] * B[y][x]) % MOD;
        return ret;
    }
    if ( Hb == 1 && Wb == 1 )
    {
        Matrix ret(Ha, List(Wa));
        for ( int y = 0 ; y < Ha ; y++ )
            for ( int x = 0 ; x < Wa ; x++ )
                ret[y][x] = (A[y][x] * B[0][0]) % MOD;
        return ret;
    }

    Matrix ret(Ha, List(Wb));
    for ( int y = 0 ; y < Ha ; y++ )
        for ( int x = 0 ; x < Wb ; x++ )
        {
            ret[y][x] = 0;
            for ( int t = 0 ; t < Wa ; t ++ )
                ret[y][x] = (ret[y][x] + A[y][t] * B[t][x]) % MOD;
        }
    return ret;
}
Matrix operator -(const Matrix &A, const Matrix &B)
{
    int H = A.size(), W = A[0].size();
    Matrix ret(H, List(W));
    for ( int y = 0 ; y < H ; y++ )
        for ( int x = 0 ; x < W ; x++ )
            ret[y][x] = (A[y][x] - B[y][x]) % MOD;
    return ret;
}
Matrix operator -(const Matrix &A)
{
    int H = A.size(), W = A[0].size();
    Matrix ret(H, List(W));
    for ( int y = 0 ; y < H ; y++ )
        for ( int x = 0 ; x < W ; x++ )
            ret[y][x] = (-A[y][x] + MOD) % MOD;
    return ret;
}
Matrix parseInum(const char*& p)
{
    int val = 0;
    for ( ; isdigit(*p); p++)
    {
        val = val * 10 + (*p - '0');
        val %= MOD;
    }
    return Matrix(1, List(1, val));
}
Matrix parseRow(const char*& p)
{
    Matrix ret = parseExpr(p);
    while ( *p )
    {
        skip(p);
        if ( *p == ']' || *p == ';' ) break;
        auto nxt = parseExpr(p);
        for ( int y = 0 ; y < ret.size() ; y ++ )
            for ( auto n: nxt[y] )
                ret[y].push_back(n);
    }
    return ret;
}
Matrix parseRowSeq(const char*& p)
{
    Matrix ret = parseRow(p);
    while ( *p )
    {
        skip(p);
        if ( *p == ']') break;
        consume(p, ';');
        auto nxt = parseRow(p);
        for (auto &row: nxt) ret.emplace_back(row);
    }
    return ret;
}
Matrix Transpose(const Matrix &A)
{
    int H = A.size(), W = A[0].size();
    Matrix ret(W, List(H));
    for ( int y = 0 ; y < H ; y++ )
        for ( int x = 0 ; x < W ; x++ )
            ret[x][y] = A[y][x];
    return ret;
}
Matrix parsePrimary(const char*& p) {
    Matrix ret;
    skip(p);
    if (isdigit(*p))
        ret = parseInum(p);
    else if (isupper(*p))
        ret = variables[*p++ - 'A'];
    else if ( consume(p, '[') )
        ret = parseRowSeq(p), consume(p, ']');
    else if ( consume(p, '(') )
        ret = parseExpr(p), consume(p, ')');

    while ( true )
    {
        if (consume(p, '(') ) // INDEXED_PRIMARY
        {
            auto A = parseExpr(p);
            consume(p, ',');
            auto B = parseExpr(p);
            consume(p, ')');

            Matrix nxt(A[0].size(), List(B[0].size()));
            for ( int y = 0 ; y < A[0].size() ; y++ )
                for ( int x = 0 ; x < B[0].size() ; x++ )
                    nxt[y][x] = ret[ A[0][y] - 1 ][ B[0][x] - 1 ];
            swap(ret, nxt);
        }
        else if ( *p == '\'') // TRANSPOSED_PRIMARY
        {
            bool isTrans = false;
            while ( consume(p, '\'') ) isTrans = !isTrans;
            if ( isTrans ) ret = Transpose(ret);
        }
        else break;
    }
    return ret;
}

Matrix parseFactor(const char*& p) {
    bool neg = false;
    while ( consume(p, '-') ) neg = !neg;
    auto ret = parsePrimary(p);
    return neg ? -ret : ret;
}

Matrix parseTerm(const char*& p) {
    auto ret = parseFactor(p);
    while (consume(p, '*') ) ret = ret * parseFactor(p);
    return ret;
}

Matrix parseExpr(const char*& p) {
    auto ret = parseTerm(p);
    while (true) {
        if ( consume(p, '+') ) ret = ret + parseTerm(p);
        else if ( consume(p, '-') ) ret = ret - parseTerm(p);
        else break;
    }
    return ret;
}
void print(const Matrix &m)
{
    int H = m.size();
    int W = m[0].size();
    for ( int y = 0 ; y < H ; y++ )
        for ( int x = 0 ; x < W ; x++ )
            cout << ( m[y][x] % MOD + MOD ) % MOD  << " \n"[x+1 == W];
}
void sol(int N) {
    for ( int i = 0 ; i < 26 ; i ++ ) variables[i].clear();

    string s;
    for (int i = 0; i < N; i++) {
        getline(cin, s);
        int varIndex = s[0] - 'A';
        while ( !s.empty() && ( s.back() == ' ' || s.back() == '.' ) ) s.pop_back();
        const char* p = s.c_str() + s.find('=') + 1;
        variables[varIndex] = parseExpr(p);
        print(variables[varIndex]);
    }
}

int main() {
#ifdef AJAVA_DEBUG
freopen("output.txt", "wt", stdout);
#endif
    cin.tie(nullptr)->sync_with_stdio(false);
    int N;
    for ( int i = 0 ; cin >> N && N != 0 ; i ++ )
    {
        cin.ignore();
        sol(N);
        cout << "-----\n";
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3548
final_rank: 3

code_snippet: #line 1 "main.cpp"
#include<bits/stdc++.h>
//#pragma GCC target("avx,avx2")
//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#ifdef LOCAL
#include <debug.hpp>
#define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (static_cast<void>(0))
#endif
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pll = pair<ll,ll>;
using pii = pair<int,int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vvvl = vector<vvl>;
using vul = vector<ull>;
using vpii = vector<pii>;
using vvpii = vector<vpii>;
using vpll = vector<pll>;
using vs = vector<string>;
template<class T> using pq = priority_queue<T,vector<T>, greater<T>>;
#define overload4(_1, _2, _3, _4, name, ...) name
#define overload3(a,b,c,name,...) name
#define rep1(n) for (ll UNUSED_NUMBER = 0; UNUSED_NUMBER < (n); ++UNUSED_NUMBER)
#define rep2(i, n) for (ll i = 0; i < (n); ++i)
#define rep3(i, a, b) for (ll i = (a); i < (b); ++i)
#define rep4(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i = (n) - 1;i >= 0;i--)
#define rrep2(i,n) for(ll i = (n) - 1;i >= 0;i--)
#define rrep3(i,a,b) for(ll i = (b) - 1;i >= (a);i--)
#define rrep4(i,a,b,c) for(ll i = (a) + ((b)-(a)-1) / (c) * (c);i >= (a);i -= c)
#define rrep(...) overload4(__VA_ARGS__, rrep4, rrep3, rrep2, rrep1)(__VA_ARGS__)
#define all1(i) begin(i) , end(i)
#define all2(i,a) begin(i) , begin(i) + a
#define all3(i,a,b) begin(i) + a , begin(i) + b
#define all(...) overload3(__VA_ARGS__, all3, all2, all1)(__VA_ARGS__)
#define sum(...) accumulate(all(__VA_ARGS__),0LL)
template<class T> bool chmin(T &a, const T &b){ if(a > b){ a = b; return 1; } else return 0; }
template<class T> bool chmax(T &a, const T &b){ if(a < b){ a = b; return 1; } else return 0; }
template<class T> auto min(const T& a){return *min_element(all(a));}
template<class T> auto max(const T& a){return *max_element(all(a));}
template<class... Ts> void in(Ts&... t);
#define INT(...) int __VA_ARGS__; in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__; in(__VA_ARGS__)
#define STR(...) string __VA_ARGS__; in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__; in(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__; in(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; in(__VA_ARGS__)
#define VEC(type, name, size) vector<type> name(size); in(name)
#define VV(type, name, h, w) vector<vector<type>> name(h, vector<type>(w)); in(name)
ll intpow(ll a, ll b){ ll ans = 1; while(b){if(b & 1) ans *= a; a *= a; b /= 2;} return ans;}
ll modpow(ll a, ll b, ll p){ ll ans = 1; a %= p;if(a < 0) a += p;while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
bool is_clamp(ll val,ll low,ll high) {return low <= val && val < high;}
void Yes() {cout << "Yes\n";return;}
void No() {cout << "No\n";return;}
void YES() {cout << "YES\n";return;}
void NO() {cout << "NO\n";return;}
template <typename T>
T floor(T a, T b) {return a / b - (a % b && (a ^ b) < 0);}
template <typename T>
T ceil(T x, T y) {return floor(x + y - 1, y);}
template <typename T>
T bmod(T x, T y) {return x - y * floor(x, y);}
template <typename T>
pair<T, T> divmod(T x, T y) {T q = floor(x, y);return {q, x - q * y};}
namespace IO{
#define VOID(a) decltype(void(a))
struct setting{ setting(){cin.tie(nullptr); ios::sync_with_stdio(false);fixed(cout); cout.precision(12);}} setting;
template<int I> struct P : P<I-1>{};
template<> struct P<0>{};
template<class T> void i(T& t){ i(t, P<3>{}); }
void i(vector<bool>::reference t, P<3>){ int a; i(a); t = a; }
template<class T> auto i(T& t, P<2>) -> VOID(cin >> t){ cin >> t; }
template<class T> auto i(T& t, P<1>) -> VOID(begin(t)){ for(auto&& x : t) i(x); }
template<class T, size_t... idx> void ituple(T& t, index_sequence<idx...>){in(get<idx>(t)...);}
template<class T> auto i(T& t, P<0>) -> VOID(tuple_size<T>{}){ituple(t, make_index_sequence<tuple_size<T>::value>{});} 
#undef VOID
}
#define unpack(a) (void)initializer_list<int>{(a, 0)...}
template<class... Ts> void in(Ts&... t){ unpack(IO :: i(t)); }
#undef unpack
constexpr long double PI = 3.141592653589793238462643383279L;
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, forward<Args>(args)...); }};

//constexpr int mod = 998244353;
constexpr int mod = 1000000007;
template <typename T> 
struct Edge {
	int from, to;
	T cost;
	Edge() = default;
	Edge(int _to, T _cost) : from(-1), to(_to), cost(_cost) {}
	Edge(int _from, int _to, T _cost) : from(_from), to(_to), cost(_cost) {}
	bool operator < (const Edge &a) const { return cost < a.cost; }
	bool operator > (const Edge &a) const { return cost > a.cost; }
    Edge &operator = (const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
    friend ostream operator<<(ostream &os, Edge &edge) { return os << edge.to; }
};
template <typename T>
using Edges = vector<Edge<T>>;
template <typename T>
using Wgraph = vector<Edges<T>>;
using Ugraph = vector<vector<int>>;
Ugraph uinput(int N, int M = -1, bool is_directed = false, int origin = 1) {
    Ugraph g(N);
    if (M == -1) M = N - 1;
    while(M--) {
        int a,b;
        cin >> a >> b;
        a -= origin, b -= origin;
        g[a].push_back(b);
        if(!is_directed) g[b].push_back(a);
    }
    return g;
}
template <typename T>
Wgraph<T> winput(int N, int M = -1, bool is_directed = false,int origin = 1) {
    Wgraph<T> g(N);
    if (M == -1) M = N - 1;
    while(M--) {
        int a,b;
        T c;
        cin >> a >> b >> c;
        a -= origin, b -= origin;
        g[a].emplace_back(b,c);
        if(!is_directed) g[b].emplace_back(a,c);
    }
    return g;
}
#line 2 "library/modint/barrett-reduction.hpp"
struct Barrett {
    using u32 = unsigned int;
    using i64 = long long;
    using u64 = unsigned long long;
    u32 m;
    u64 im;
    Barrett() : m(), im() {}
    Barrett(int n) : m(n), im(u64(-1) / m + 1) {}
    constexpr inline i64 quo(u64 n) {
        u64 x = u64((__uint128_t(n) * im) >> 64);
        u32 r = n - x * m;
        return m <= r ? x - 1 : x;
    }
    constexpr inline i64 rem(u64 n) {
        u64 x = u64((__uint128_t(n) * im) >> 64);
        u32 r = n - x * m;
        return m <= r ? r + m : r;
    }
    constexpr inline pair<i64, int> quorem(u64 n) {
        u64 x = u64((__uint128_t(n) * im) >> 64);
        u32 r = n - x * m;
        if (m <= r) return {x - 1, r + m};
        return {x, r};
    }
    constexpr inline i64 pow(u64 n, i64 p) {
        u32 a = rem(n), r = m == 1 ? 0 : 1;
        while (p) {
            if (p & 1) r = rem(u64(r) * a);
            a = rem(u64(a) * a);
            p >>= 1;
        }
        return r;
    }
};
#line 3 "library/modint/ArbitaryModint.hpp"
struct ArbitraryModint {
    int x;
    ArbitraryModint():x(0) {}
    ArbitraryModint(int64_t y) {
        int z = y % get_mod();
        if(z < 0) z += get_mod();
        x = z;
    }
    ArbitraryModint &operator+=(const ArbitraryModint &p) {
        if((x += p.x) >= get_mod()) x -= get_mod();
        return *this;
    }
    ArbitraryModint &operator-=(const ArbitraryModint &p) {
        if((x += get_mod() - p.x) >= get_mod()) x -= get_mod();
        return *this;
    }
    ArbitraryModint &operator*=(const ArbitraryModint &p) {
        x = rem((unsigned long long)x * p.x);
        return *this;
    }
    ArbitraryModint &operator/=(const ArbitraryModint &p) {
        *this *= p.inverse();
        return *this;
    }
    ArbitraryModint operator-() const {return ArbitraryModint(-x);};
    ArbitraryModint operator+(const ArbitraryModint &p) const{
        return ArbitraryModint(*this) += p;
    }
    ArbitraryModint operator-(const ArbitraryModint &p) const{
        return ArbitraryModint(*this) -= p;
    }
    ArbitraryModint operator*(const ArbitraryModint &p) const{
        return ArbitraryModint(*this) *= p;
    }
    ArbitraryModint operator/(const ArbitraryModint &p) const {
        return ArbitraryModint(*this) /= p;
    }
    bool operator==(const ArbitraryModint &p) {return x == p.x;}
    bool operator!=(const ArbitraryModint &p) {return x != p.x;}
    ArbitraryModint inverse() const {
        int a = x,b = get_mod(),u = 1,v = 0,t;
        while(b > 0) {
            t = a / b;
            swap(a -= t * b,b);
            swap(u -= t * v,v);
        }
        return ArbitraryModint(u);
    }
    ArbitraryModint pow(int64_t n) const {
        ArbitraryModint ret(1),mul(x);
        while(n > 0) {
            if(n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os,const ArbitraryModint &p) {
        return os << p.x;
    }
    friend istream &operator>>(istream &is,ArbitraryModint &a) {
        int64_t t;
        is >> t;
        a = ArbitraryModint(t);
        return (is);
    }
    int get() const {return x;}
    inline unsigned int rem(unsigned long long p) {return barrett().rem(p);};
    static inline Barrett &barrett() {
        static Barrett b;
        return b;
    }
    static inline int &get_mod() {
        static int mod = 0;
        return mod;
    }
    static void set_mod(int md) {
        assert(0 < md && md <= (1LL << 30) - 1);
        get_mod() = md;
        barrett() = Barrett(md);
    }
};
#line 146 "main.cpp"
using mint = ArbitraryModint;
using vm = vector<mint>;
using vvm = vector<vm>;
using vvvm = vector<vvm>;
#line 2 "library/matrix/matrix.hpp"
template <class T>
struct Matrix {
    vector<vector<T>> A;
    Matrix() = default;
    Matrix(int n, int m) : A(n, vector<T>(m, T())) {}
    Matrix(int n) : A(n, vector<T>(n, T())){};
    int H() const { return A.size(); }
    int W() const { return A[0].size(); }
    int size() const { return A.size(); }
    inline const vector<T> &operator[](int k) const { return A[k]; }
    inline vector<T> &operator[](int k) { return A[k]; }
    static Matrix I(int n) {
        Matrix mat(n);
        for (int i = 0; i < n; i++) mat[i][i] = 1;
        return (mat);
    }
    Matrix &operator+=(const Matrix &B) {
        int n = H(), m = W();
        assert(n == B.H() && m == B.W());
        for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) (*this)[i][j] += B[i][j];
        return (*this);
    }
    Matrix &operator-=(const Matrix &B) {
        int n = H(), m = W();
        assert(n == B.H() && m == B.W());
        for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) (*this)[i][j] -= B[i][j];
        return (*this);
    }
    Matrix &operator*=(const Matrix &B) {
        int n = H(), m = B.W(), p = W();
        assert(p == B.H());
        vector<vector<T>> C(n, vector<T>(m, T{}));
        for (int i = 0; i < n; i++) {
            for (int k = 0; k < p; k++) {
                if((*this)[i][k] == 0) continue;
                for (int j = 0; j < m; j++) C[i][j] += (*this)[i][k] * B[k][j];
            }
        }
        A.swap(C);
        return (*this);
    }
    Matrix &operator^=(long long k) {
        Matrix B = Matrix::I(H());
        while (k > 0) {
            if (k & 1) B *= *this;
            *this *= *this;
            k >>= 1LL;
        }
        A.swap(B.A);
        return (*this);
    }
    Matrix operator+(const Matrix &B) const { return (Matrix(*this) += B); }
    Matrix operator-(const Matrix &B) const { return (Matrix(*this) -= B); }
    Matrix operator*(const Matrix &B) const { return (Matrix(*this) *= B); }
    Matrix operator^(const long long k) const { return (Matrix(*this) ^= k); }
    bool operator==(const Matrix &B) const {
        assert(H() == B.H() && W() == B.W());
        for (int i = 0; i < H(); i++) for (int j = 0; j < W(); j++) {
            if (A[i][j] != B[i][j]) return false;
        }
        return true;
    }
    bool operator!=(const Matrix &B) const {
        assert(H() == B.H() && W() == B.W());
        for (int i = 0; i < H(); i++) for (int j = 0; j < W(); j++) {
            if (A[i][j] != B[i][j]) return true;
        }
        return false;
    }
    friend ostream &operator<<(ostream &os, const Matrix &p) {
        int n = p.H(), m = p.W();
        for (int i = 0; i < n; i++) {
            os << (i ? "   " : "") << "[";
            for (int j = 0; j < m; j++) {
                os << p[i][j] << (j + 1 == m ? "]\n" : ",");
            }
        }
        return (os);
    }
    T determinant() const {
        Matrix B(*this);
        assert(H() == W());
        T ret = 1;
        for (int i = 0; i < H(); i++) {
            int idx = -1;
            for (int j = i; j < W(); j++) {
                if (B[j][i] != 0) {
                    idx = j;
                    break;
                }
            }
            if (idx == -1) return 0;
            if (i != idx) {
                ret *= T(-1);
                swap(B[i], B[idx]);
            }
            ret *= B[i][i];
            T inv = T(1) / B[i][i];
            for (int j = 0; j < W(); j++) {
                B[i][j] *= inv;
            }
            for (int j = i + 1; j < H(); j++) {
                T a = B[j][i];
                if (a == 0) continue;
                for (int k = i; k < W(); k++) {
                    B[j][k] -= B[i][k] * a;
                }
            }
        }
        return ret;
    }
};
#line 151 "main.cpp"
using T = Matrix<mint>;
vector<Matrix<mint>> VAR(26);
T term(string &s,int &id);
T expression(string &s,int &id);
T factor(string &s,int &id);
T primary(string &s,int &id);
T matrix(string &s,int &id);
T row_seq(string &s,int &id);
T row(string &s,int &id);
mint number(string &s,int &id) {
    mint ret = 0;
    while(isdigit(s[id])) {
        ret *= 10;
        ret += s[id++] - '0';
    }
    return ret;
}
T row(string &s,int &id) {
    T ret = expression(s,id);
    //debug(ret,id,s[id],s);
    while(1) {
        if(s[id] == ' ') {
            id++;
            T ret2 = expression(s,id);
            assert(ret.H() == ret2.H());
            T ret3(ret.H(),ret.W() + ret2.W());
            rep(i,ret.H()) {
                rep(j,ret.W()) {
                    ret3[i][j] = ret[i][j];
                }
            }
            rep(i,ret2.H()) {
                rep(j,ret2.W()) {
                    ret3[i][j + ret.W()] = ret2[i][j];
                }
            }
            swap(ret,ret3);
        }
        else break;
    }
    return ret;
}
T row_seq(string &s,int &id) {
    T ret = row(s,id);
    while(1) {
        if(s[id] == ';') {
            id++;
            T ret2 = row(s,id);
            assert(ret.W() == ret2.W());
            T ret3(ret.H() + ret2.H(),ret.W());
            rep(i,ret.H()) {
                rep(j,ret.W()) ret3[i][j] = ret[i][j];
            }
            rep(i,ret2.H()) {
                rep(j,ret2.W()) ret3[i+ret.H()][j] = ret2[i][j];
            }
            swap(ret,ret3);
        }
        else break;
    }
    return ret;
}
T matrix(string &s,int &id) {
    assert(s[id] == '[');
    id++;
    T ret = row_seq(s,id);
    //debug(ret);
    assert(s[id] == ']');
    id++;
    return ret;
}
T primary(string &s,int &id) {
    T ret;
	if(isdigit(s[id])) {
        mint res = number(s,id);
        ret = Matrix<mint>(1);
        ret[0][0] = res;
    }
    else if('A' <= s[id] && s[id] <= 'Z') {
        ret = VAR[s[id] - 'A'];
        id++;
    }
    else if(s[id] == '[') {
        ret = matrix(s,id);
    }
    else if(s[id] == '(') {
        id++;
        ret = expression(s,id);
        assert(s[id] == ')');
        id++;
    }
    while(1) {
        if(s[id] == '(') {
            id++;
            T ret2 = expression(s,id);
            assert(s[id] == ',');
            id++;
            T ret3 = expression(s,id);
            assert(s[id] == ')');
            id++;
            T ret4(ret2.W(),ret3.W());
            rep(i,ret2.W()) {
                rep(j,ret3.W()) {
                    ret4[i][j] = ret[ret2[0][i].get() - 1][ret3[0][j].get() - 1];
                }
            }
            swap(ret,ret4);
        }
        else if(s[id] == '\'') {
            id++;
            T ret2(ret.W(),ret.H());
            rep(i,ret.H()) {
                rep(j,ret.W()) {
                    ret2[j][i] = ret[i][j];
                }
            }
            swap(ret,ret2);
        }
        else break;
    }
    return ret;
}
T factor(string &s,int &id) {
	int co = 1;
	T ret;
	if(s[id] == '-') {
		co = -1;
		id++;
		ret = factor(s,id);
	}
	else ret = primary(s,id);
	rep(i,ret.H()) {
		rep(j,ret.W()) {
			ret[i][j] *= co;
		}
	}
	return ret;
}
T term(string &s,int &id) {
    T ret = factor(s,id);
    while(1) {
        if(s[id] == '*') {
            id++;
            T ret2 = factor(s,id);
            //debug(ret,ret2);
            if(ret.H() == ret.W() && ret.H() == 1) {
                rep(i,ret2.H()) {
                    rep(j,ret2.W()) {
                        ret2[i][j] *= ret[0][0];
                    }
                }
                swap(ret,ret2);
            }
            else if(ret2.H() == ret2.W() && ret2.H() == 1) {
                rep(i,ret.H()) {
                    rep(j,ret.W()) {
                        ret[i][j] *= ret2[0][0];
                    }
                }
            }
            else ret *= ret2;
        }
        else break;
    }
    return ret;
}
T expression(string &s,int &id) {
    T ret = term(s,id);
	while(1) {
		if(s[id] == '+') {
			id++;
			T ret2 = term(s,id);
			ret += ret2;
		}
		else if(s[id] == '-') {
			id++;
			T ret2 = term(s,id);
			ret -= ret2;
		}
		else break;
	}
    return ret;
}

int main() {
	mint::set_mod(32768);
    string s,t;
	while(1) {
		getline(cin,t);
        int x = stoi(t);
		if(x == 0) break;
		while(x--) {
			getline(cin,s);
			int p = s[0] - 'A';
			int id = 2;
            T ret = expression(s,id);
            VAR[p] = ret;
            rep(i,ret.H()) {
                rep(j,ret.W()) {
                    cout << ret[i][j] << " \n"[j == ret.W() - 1];
                }
            }
		}
        cout << "-----\n";
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3760
final_rank: 11

code_snippet: #include <bits/stdc++.h>

struct Matrix {
    static constexpr int MOD = 32768;
    std::vector<std::vector<int>> data;

    Matrix() {}
    explicit Matrix(int value): data(1, std::vector<int>(1, value)) {}
    explicit Matrix(int n, int m): data(n, std::vector<int>(m)) {}

    std::pair<int, int> size() const {
        return {data.size(), data.front().size()};
    }

    friend std::ostream& operator<<(std::ostream& os, const Matrix& mat) {
        auto [n, m] = mat.size();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                os << mat.data[i][j];
                if (j + 1 != m) {
                    os << ' ';
                }
            }
            if (i + 1 != n) {
                os << '\n';
            }
        }
        return os;
    }

    bool is_scalar() const {
        return data.size() == 1 && data.front().size() == 1;
    }

    friend Matrix operator+(const Matrix& lhs, const Matrix& rhs) {
        if (lhs.is_scalar() ^ rhs.is_scalar()) {
            if (lhs.is_scalar()) {
                return lhs.data.front().front() + rhs;
            } else {
                return rhs.data.front().front() + lhs;
            }
        }

        auto [n, m] = lhs.size();

        Matrix res(lhs);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                res.data[i][j] += rhs.data[i][j];
                res.data[i][j] %= MOD;
            }
        }

        return res;
    }

    friend Matrix operator-(const Matrix& lhs, const Matrix& rhs) {
        if (lhs.is_scalar() ^ rhs.is_scalar()) {
            if (lhs.is_scalar()) {
                return lhs.data.front().front() - rhs;
            } else {
                return rhs.data.front().front() - lhs;
            }
        }

        auto [n, m] = lhs.size();

        Matrix res(lhs);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                res.data[i][j] -= rhs.data[i][j];
                res.data[i][j] = (res.data[i][j] + MOD) % MOD;
            }
        }

        return res;
    }

    friend Matrix operator*(const Matrix& lhs, const Matrix& rhs) {
        if (lhs.is_scalar() ^ rhs.is_scalar()) {
            if (lhs.is_scalar()) {
                return lhs.data.front().front() * rhs;
            } else {
                return rhs.data.front().front() * lhs;
            }
        }

        auto [n, m] = lhs.size();
        int l = rhs.data.front().size();

        Matrix res(n, l);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                for (int k = 0; k < l; k++) {
                    res.data[i][k] += lhs.data[i][j] * rhs.data[j][k];
                    res.data[i][k] %= MOD;
                }
            }
        }

        return res;
    }

    friend Matrix operator+(int value, const Matrix& rhs) {
        auto [n, m] = rhs.size();
        auto res(rhs);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                res.data[i][j] += value;
                res.data[i][j] %= MOD;
            }
        }
        return res;
    }

    friend Matrix operator-(int value, const Matrix& rhs) {
        auto [n, m] = rhs.size();
        auto res(rhs);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                res.data[i][j] -= value;
                res.data[i][j] = (res.data[i][j] + MOD) % MOD;
            }
        }
        return res;
    }

    friend Matrix operator*(int value, const Matrix& rhs) {
        auto [n, m] = rhs.size();
        auto res(rhs);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                res.data[i][j] *= value;
                res.data[i][j] %= MOD;
            }
        }
        return res;
    }

    Matrix operator-() {
        auto [n, m] = size();
        auto res(*this);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                res.data[i][j] = (MOD - res.data[i][j]) % MOD;
            }
        }
        return res;
    }

    Matrix transpose() {
        auto [n, m] = size();
        Matrix mat(m, n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                mat.data[j][i] = data[i][j];
            }
        }
        return mat;
    }

    Matrix operator()(const Matrix& lhs, const Matrix& rhs) {
        auto [n, m] = size();
        auto [n1, m1] = lhs.size();
        auto [n2, m2] = rhs.size();
        Matrix mat(m1, m2);

        for (int i = 0; i < n1; i++) {
            for (int j = 0; j < m1; j++) {}
        }

        for (int i = 0; i < n2; i++) {
            for (int j = 0; j < m2; j++) {}
        }

        for (int i = 0; i < m1; i++) {
            for (int j = 0; j < m2; j++) {
                mat.data[i][j] = data[lhs.data[0][i] - 1][rhs.data[0][j] - 1];
            }
        }

        return mat;
    }

    Matrix add_row(const Matrix& mat) {
        auto [n1, m1] = size();
        auto [n2, m2] = mat.size();

        Matrix res(n1 + n2, m1);
        for (int i = 0; i < n1; i++) {
            for (int j = 0; j < m1; j++) {
                res.data[i][j] = data[i][j];
            }
        }

        for (int i = 0; i < n2; i++) {
            for (int j = 0; j < m1; j++) {
                res.data[i + n1][j] = mat.data[i][j];
            }
        }

        return res;
    }

    Matrix add_column(const Matrix& mat) {
        auto [n1, m1] = size();
        auto [n2, m2] = mat.size();
        Matrix res(n1, m1 + m2);
        for (int i = 0; i < n1; i++) {
            for (int j = 0; j < m1; j++) {
                res.data[i][j] = data[i][j];
            }
        }

        for (int i = 0; i < n2; i++) {
            for (int j = 0; j < m2; j++) {
                res.data[i][j + m1] = mat.data[i][j];
            }
        }

        return res;
    }
};

struct Parser {
    using Iter = std::string::const_iterator&;
    std::vector<std::string> lines;
    std::string line;
    std::map<char, Matrix> database;

    void consume(Iter it, char c) {
        it++;
    }

    Parser(const std::vector<std::string>& s): lines(s) {}

    std::vector<Matrix> parse() {
        std::vector<Matrix> mats;
        for (int i = 0; i < (int)lines.size(); i++) {
            line = lines[i];
            auto it = line.cbegin();
            auto [var, mat] = assignment(it);

            mats.push_back(mat);
            database[var] = mat;
        }
        return mats;
    }

    std::pair<char, Matrix> assignment(Iter it) {
        char assignment_var = *it;
        consume(it, assignment_var);
        consume(it, '=');
        Matrix res = expr(it);
        consume(it, '.');
        return {assignment_var, res};
    }

    Matrix var(Iter it) {
        char c = *it;
        consume(it, c);
        return database[c];
    }

    Matrix expr(Iter it) {
        Matrix res = term(it);
        while (it != line.end() && (*it == '+' || *it == '-')) {
            if (*it == '+') {
                consume(it, '+');
                res = res + term(it);
            } else {
                consume(it, '-');
                res = res - term(it);
            }
        }
        return res;
    }

    Matrix term(Iter it) {
        Matrix res = factor(it);
        while (it != line.end() && *it == '*') {
            consume(it, '*');
            res = res * factor(it);
        }
        return res;
    }

    Matrix factor(Iter it) {
        bool inv = false;
        while (it != line.end() && *it == '-') {
            consume(it, '-');
            inv ^= true;
        }
        Matrix res = primary(it);
        if (inv) {
            res = -res;
        }
        return res;
    }

    Matrix primary(Iter it) {
        Matrix res;
        if (std::isdigit(*it)) {
            res = inum(it);
        } else if (std::isupper(*it)) {
            res = var(it);
        } else if (*it == '[') {
            res = matrix(it);
        } else if (*it == '(') {
            consume(it, '(');
            res = expr(it);
            consume(it, ')');
        }

        while (it != line.end() && (*it == '(' || *it == '\'')) {
            if (*it == '(') {
                res = indexed_primary(it, res);
            } else if (*it == '\'') {
                res = transposed_primary(it, res);
            }
        }

        return res;
    }

    Matrix indexed_primary(Iter it, Matrix mat) {
        consume(it, '(');
        Matrix lhs = expr(it);
        consume(it, ',');
        Matrix rhs = expr(it);
        consume(it, ')');

        return mat(lhs, rhs);
    }

    Matrix transposed_primary(Iter it, Matrix mat) {
        consume(it, '\'');
        return mat.transpose();
    }

    Matrix matrix(Iter it) {
        consume(it, '[');
        Matrix res = row_seq(it);
        consume(it, ']');
        return res;
    }

    Matrix row_seq(Iter it) {
        Matrix res = row(it);
        while (it != line.end() && *it == ';') {
            consume(it, ';');
            res = res.add_row(row(it));
        }
        return res;
    }

    Matrix row(Iter it) {
        Matrix res = expr(it);
        while (it != line.end() && *it == ' ') {
            consume(it, ' ');
            res = res.add_column(expr(it));
        }
        return res;
    }

    Matrix inum(Iter it) {
        int res = digit(it);
        while (it != line.end() && std::isdigit(*it)) {
            res = 10 * res + digit(it);
        }
        return Matrix(res);
    }

    int digit(Iter it) {
        char res = *it;
        consume(it, res);
        return res - '0';
    }
};

int main() {
    int n;
    while (std::cin >> n) {
        if (n == 0) break;
        std::cin.ignore();
        std::vector<std::string> lines(n);
        for (int i = 0; i < n; i++) {
            std::getline(std::cin, lines[i]);
        }
        Parser parser(lines);
        auto mats = parser.parse();
        for (auto mat: mats) {
            std::cout << mat << std::endl;
        }
        std::cout << "-----" << std::endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3664
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef __int128_t lll;
typedef long double ld;
typedef pair<ll, ll> pl;
typedef tuple<ll, ll, ll> tt;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl> vvvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<vvd> vvvd;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<char> vc;
typedef vector<vc> vvc;
typedef vector<vvc> vvvc;
typedef vector<pl> vp;
typedef vector<tt> vt;
typedef vector<string> vs;

const ll INF = 1000000010;
const ll INFL = INF * INF;
const ld epsilon = 1e-10;

#define ovl(a, b, c, d, e, ...) e
#define pb push_back
#define eb emplace_back
#define MP make_pair
#define DEBUG(...) DEBUG_(#__VA_ARGS__, __VA_ARGS__)
#define REP1(i, r) for (int i = 0; i < (r); i++)
#define REP2(i, l, r) for (int i = (l); i < (r); i++)
#define REP3(i, l, r, d) for (int i = (l); i < (r); i += (d))
#define REP(...) ovl(__VA_ARGS__, REP3, REP2, REP1)(__VA_ARGS__)
#define RREP1(i, r) for (int i = (r)-1; i >= 0; i--)
#define RREP2(i, l, r) for (int i = (r)-1; i >= (l); i--)
#define RREP3(i, l, r, d) for (int i = (r)-1; i >= (l); i -= (d))
#define RREP(...) ovl(__VA_ARGS__, RREP3, RREP2, RREP1)(__VA_ARGS__)
#define EACH1(x, a) for (auto &x : a)
#define EACH2(x, y, a) for (auto &[x, y] : a)
#define EACH3(x, y, z, a) for (auto &[x, y, z] : a)
#define EACH(...) ovl(__VA_ARGS__, EACH3, EACH2, EACH1)(__VA_ARGS__)
#define ALL(x) begin(x), end(x)
#define RALL(x) (x).rbegin(), (x).rend()
#define sz(x) (ll) x.size()
#define LB(a, x) (lower_bound(ALL(a), x) - a.begin())
#define UB(a, x) (upper_bound(ALL(a), x) - a.begin())
#define FLG(x, i) (((x) >> (i)) & 1)
#define CNTBIT(x) __builtin_popcountll(x)
#define IN(x, a, b) ((a) <= (x) && (x) < (b))
#define int ll

template <class T>
void DEBUG_(string_view name, const T &a) {
    cerr << name << ": " << a << endl;
}

template <class T>
void DEBUG_(string_view name, const vector<T> &a) {
    cerr << name << ": ";
    REP(i, sz(a)) cerr << a[i] << " ";
    cerr << endl;
}

template <class T, class U>
bool chmax(T &x, const U &y) {
    return x < y ? x = y, 1 : 0;
}
template <class T, class U>
bool chmin(T &x, const U &y) {
    return x > y ? x = y, 1 : 0;
}

//-----------------------------------------------------------------------

typedef string::const_iterator State;
typedef vector<vector<int>> Mat;

constexpr int MOD = 1 << 15;

Mat matadd(const Mat &m1, const Mat &m2) {
    assert(m1.size() == m2.size() && m1[0].size() == m2[0].size());
    Mat m3 = m1;
    REP(h, (int)m1.size())
    REP(w, (int)m1[0].size()) {
        m3[h][w] += m2[h][w];
        m3[h][w] %= MOD;
    }
    return m3;
}

Mat matsub(const Mat &m1, const Mat &m2) {
    assert(m1.size() == m2.size() && m1[0].size() == m2[0].size());
    Mat m3 = m1;
    REP(h, (int)m1.size())
    REP(w, (int)m1[0].size()) {
        m3[h][w] += MOD - m2[h][w] % MOD;
        m3[h][w] %= MOD;
    }
    return m3;
}

Mat matmul(const Mat &m1, const Mat &m2) {
    if (int(m1.size()) == 1 && int(m1[0].size()) == 1) {
        Mat m3 = m2;
        REP(h, int(m3.size()))
        REP(w, int(m3[0].size())) {
            m3[h][w] *= m1[0][0];
            m3[h][w] %= MOD;
        }
        return m3;
    } else if (int(m2.size()) == 1 && int(m2[0].size()) == 1) {
        Mat m3 = m1;
        REP(h, int(m3.size()))
        REP(w, int(m3[0].size())) {
            m3[h][w] *= m2[0][0];
            m3[h][w] %= MOD;
        }
        return m3;
    } else {
        assert(m1[0].size() == m2.size());
        Mat m3(m1.size(), vl(m2[0].size(), 0));
        REP(i, (int)m1.size())
        REP(j, (int)m2[0].size())
        REP(k, (int)m1[0].size()) {
            m3[i][j] += m1[i][k] * m2[k][j] % MOD;
            m3[i][j] %= MOD;
        }
        return m3;
    }
}

Mat unary_minus(const Mat &m) {
    Mat m3 = m;
    REP(h, (int)m.size())
    REP(w, (int)m[0].size()) { m3[h][w] = MOD - m[h][w]; }
    return m3;
}

Mat mattranspose(const Mat &m) {
    Mat m3(m[0].size(), vl(m.size()));
    REP(h, (int)m.size())
    REP(w, (int)m[0].size()) { m3[w][h] = m[h][w]; }
    return m3;
}

Mat matindex(const Mat &p, const Mat &m1, const Mat &m2) {
    assert((int)m1.size() == 1 && (int)m2.size() == 1);
    Mat m3(m1[0].size(), vl(m2[0].size()));
    REP(h, (int)m1[0].size())
    REP(w, (int)m2[0].size()) { m3[h][w] = p[m1[0][h] - 1][m2[0][w] - 1]; }
    return m3;
}

map<string, Mat> store;

Mat assignment(State &bein);
string var(State &begin);
Mat expr(State &begin);
Mat term(State &begin);
Mat factor(State &begin);
Mat primary(State &begin);
Mat matrix(State &begin);

Mat assignment(State &begin) {
    string X = var(begin);
    assert(*begin == '=');
    begin++;
    Mat mat = expr(begin);
    store[X] = mat;
    return mat;
}

string var(State &begin) {
    assert('A' <= *begin && *begin <= 'Z');
    string ret(1, *begin);
    begin++;
    return ret;
}

Mat expr(State &begin) {
    Mat mat = term(begin);
    while (*begin != '.') {
        if (*begin == '+') {
            begin++;
            Mat mat2 = term(begin);
            mat = matadd(mat, mat2);
        } else if (*begin == '-') {
            begin++;
            Mat mat2 = term(begin);
            mat = matsub(mat, mat2);
        } else {
            break;
        }
    }
    return mat;
}

Mat term(State &begin) {
    Mat mat = factor(begin);
    while (*begin == '*') {
        begin++;
        Mat mat2 = factor(begin);
        mat = matmul(mat, mat2);
    }
    return mat;
}

Mat factor(State &begin) {
    if (*begin == '-') {
        begin++;
        return unary_minus(factor(begin));
    } else {
        return primary(begin);
    }
}

int inum(State &begin) {
    int ret = 0;
    while (isdigit(*begin)) {
        ret *= 10;
        ret %= MOD;
        ret += *begin - '0';
        ret %= MOD;
        begin++;
    }
    // DEBUG(*begin);
    return ret;
}

Mat row(State &begin) {
    // DEBUG("row");
    Mat mat = expr(begin);
    // DEBUG(*begin);
    while (*begin == ' ') {
        begin++;
        Mat mat2 = expr(begin);
        // DEBUG(mat2);
        assert(mat.size() == mat2.size());
        REP(h, int(mat.size())) {
            EACH(e, mat2[h]) { mat[h].pb(e); }
        }
    }
    return mat;
}

Mat rowseq(State &begin) {
    Mat mat = row(begin);
    while (*begin == ';') {
        begin++;
        Mat mat2 = row(begin);
        EACH(r, mat2) { mat.pb(r); }
    }
    return mat;
}

Mat primary_sub(State &begin) {
    if (isdigit(*begin)) {
        return Mat(1, vl(1, inum(begin)));
    }
    if ('A' <= *begin && *begin <= 'Z') {
        Mat ret = store[string(1, *begin)];
        begin++;
        return ret;
    }
    if (*begin == '[') {
        begin++;
        Mat mat = rowseq(begin);
        assert(*begin == ']');
        begin++;
        return mat;
    }
    if (*begin == '(') {
        begin++;
        Mat mat = expr(begin);
        assert(*begin == ')');
        begin++;
        return mat;
    }
    assert(false);
}

Mat primary(State &begin) {
    Mat p = primary_sub(begin);
    while (*begin == '(' || *begin == '\'') {
        if (*begin == '(') {
            begin++;
            Mat mat1 = expr(begin);
            assert(*begin == ',');
            begin++;
            Mat mat2 = expr(begin);
            assert(*begin == ')');
            begin++;
            p = matindex(p, mat1, mat2);
        } else {
            begin++;
            p = mattranspose(p);
        }
    }
    return p;
}

vector<Mat> solve(int N) {
    store.clear();
    vector<Mat> mats;
    REP(i, N) {
        string S;
        getline(cin, S);
        // DEBUG(S);
        State begin = S.begin();
        Mat mat = assignment(begin);
        // DEBUG("mat");
        // EACH(m, mat) { DEBUG(m); }
        mats.pb(mat);
    }
    return mats;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(15);

    vector<vector<Mat>> answers;
    while (true) {
        string n;
        getline(cin, n);
        State begin = n.begin();
        int N = inum(begin);
        if (N == 0) break;
        // DEBUG(N);
        vector<Mat> answer = solve(N);
        answers.pb(answer);
    }

    EACH(as, answers) {
        EACH(a, as) {
            REP(h, (int)a.size()) {
                REP(w, (int)a[h].size()) {
                    cout << a[h][w] << (w == int(a[h].size()) - 1 ? "" : " ");
                }
                cout << endl;
            }
        }
        cout << "-----" << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4312
final_rank: 19

code_snippet: #pragma region ngng628_library

#include <cassert>
#include <numeric>
#include <type_traits>
#include <utility>

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using mint = atcoder::static_modint<32768>;
#include <bits/stdc++.h>
#define int Int
#define float Float
#define overload3(_1,_2,_3,name,...) name
#define _step(n) _rep(_,n)
#define _rep(i,n) _repr(i,0,n)
#define _repr(i,b,e) for(int i=(b), i##_len=(e); i<i##_len; ++i)
#define rep(...) overload3(__VA_ARGS__, _repr, _rep, _step)(__VA_ARGS__)
#define _reps(i,n) _reprs(i,1,n)
#define _reprs(i,b,e) for(int i=(b), i##_len=(e); i<=i##_len; ++i)
#define reps(...) overload3(__VA_ARGS__, _reprs, _reps)(__VA_ARGS__)
#define rrep(i,n) for(int i=(int)(n)-1; i>=0; --i)
#define rreps(i,n) for(int i=(n); i>0; --i)
#define all(v) std::begin(v), std::end(v)
#define rall(v) std::rbegin(v), std::rend(v)
#define pb push_back
#define eb emplace_back
#define len(v) ssize(std::size(v))
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
using Int = long long;
using Float = long double;
using int32 = int32_t;
using int64 = int64_t;
using uint32 = uint32_t;
using uint64 = uint64_t;
using usize = size_t;
using ssize = ptrdiff_t;
template<class T> using vec = vector<T>;
template<class T> using MaxHeap = priority_queue<T>;
template<class T> using MinHeap = priority_queue<T, vec<T>, greater<T>>;
using pii = pair<int, int>;
using vi = vec<int>;
using vvi = vec<vi>;
using vvvi = vec<vvi>;
using vb = basic_string<bool>;
using vvb = vec<vb>;
using vvvb = vec<vvb>;
constexpr int OO = (1LL<<62)-(1LL<<31);
template<class T> string join(const vec<T>& v){ stringstream s; for (T t : v) s << ' ' << t; return s.str().substr(1); }
template<class T> ostream& operator <<(ostream& os, const vec<T>& v){ if (len(v)) os << join(v); return os; }
template<class T> ostream& operator <<(ostream& os, const vec<vec<T>>& v){
   rep (i, len(v)) if (len(v[i])) os << join(v[i]) << (i-len(v)+1 ? "\n" : "");
   return os;
}
template<class T, class U> ostream& operator <<(ostream& os, const pair<T, U>& p){ return os << p.first << ' ' << p.second; }
template<class T, class U, class V>
ostream& operator <<(ostream& os, const tuple<T, U, V>& t){ return os << get<0>(t) << " " << get<1>(t) << " " << get<2>(t); }
struct Scanner {
   Scanner() = default;
   int nextInt(int o = 0) const {
      char c = skip();
      int r = c - '0', sgn = 1;
      if (c == '-') sgn = -1, r = gc() & 0xf;
      else if (c == '+') r = gc() & 0xf;
      while (!isspace(c = gc())) r = 10 * r + (c & 0xf);
      return sgn * r + o;
   }
   string nextLine() const { char c; string r; while ((c = gc()) != '\n') r.pb(c); return r; }
private:
   char skip() const { char c; while (isspace(c = getchar())) {} return c; }
   inline char gc() const { return getchar(); }
} sc;
istream& operator >>(istream& is, mint& r){ int t; is >> t; r = t; return is; }
ostream& operator <<(ostream& os, const mint& r){ return os << r.val(); }
mint operator"" _mod_m(unsigned long long n) { return n; }
using vm = vec<mint>;
using vvm = vec<vm>;
using vvvm = vec<vvm>;
# pragma endregion ngng628_library

template <class T>
struct Matrix {
   // コンストラクタ
   Matrix() : m(vec<vec<T>>()) {}
   Matrix(int n) : m(vec<vec<T>>(n, vec<T>(n))) {}
   Matrix(int h, int w) : m(vec<vec<T>>(h, vec<T>(w, 0))) {}
   Matrix(int h, int w, T d) : m(vec<vec<T>>(h, vec<T>(w, d))){}
   Matrix(const vec<vec<T>>& _m) : m(_m){}

   // 単位行列
   const static Matrix Identity(const int n) {
      Matrix mat(n);
      rep (i, n) mat[i][i] = T(1);
      return mat;
   }

   // 要素アクセス
   vec<T> operator[](const int i) const { return m[i]; }
   vec<T>& operator[](const int i) { return m[i]; }
   T operator ()(const int i, const int j) const { return m[i][j]; }
   T& operator ()(const int i, const int j) { return m[i][j]; }

   // ゲッター
   [[nodiscard]] constexpr int n_rows() const { return len(m); }
   [[nodiscard]] constexpr int n_cols() const { return len(m[0]); }

   // 行・列の拡張
   void resize(const int h, const int w) { m.resize(h, w, T()); }
   void push_back_row(const vec<T>& v) { m.push_back(v); }
   void push_back_col(const vec<T>& v) { rep (i, n_rows()) m[i].push_back(v[i]); }
   void pop_back_row() { m.pop_back(); }
   void pop_back_col() { rep (i, n_rows()) m[i].pop_back(); }

   // 四則演算とべき乗
   Matrix& operator +=(const Matrix& other) {
      const int r = n_rows();
      const int c = n_cols();
      assert(r == other.n_rows() and c == other.n_cols());
      rep (i, r) rep (j, c) (*this)(i, j) += other(i, j);
      return *this;
   }
   Matrix& operator -=(const Matrix& other) {
      const int r = n_rows();
      const int c = n_cols();
      assert(r == other.n_rows() and c == other.n_cols());
      rep (i, r) rep (j, c) (*this)(i, j) -= other(i, j);
      return *this;
   }
   Matrix& operator *=(const Matrix& other) {
      const int r = n_rows(), c = other.n_cols(), p = n_cols();
      assert(p == other.n_rows());
      vec<vec<T>> v(r, vec<T>(c, T(0)));
      rep (i, r) rep (j, c) rep (k, p) v[i][j] = (v[i][j] + (*this)(i, k) * other(k, j));
      m.swap(v);
      return *this;
   }
   Matrix& operator ^=(int n) {
      Matrix res = Matrix::Identity(n_rows());
      Matrix x = *this;
      while (n > 0) {
         if (n & 1) res *= x;
         x *= x;
         n >>= 1;
      }
      swap(m, res.m);
      return *this;
   }

   friend Matrix operator +(const Matrix& a, const Matrix& b) { return Matrix(a) += b; }
   friend Matrix operator -(const Matrix& a, const Matrix& b) { return Matrix(a) -= b; }
   friend Matrix operator *(const Matrix& a, const Matrix& b) { return Matrix(a) *= b; }
   friend Matrix operator ^(const Matrix& a, const int n) { return Matrix(a) ^= n; }

   // スカラー倍
   Matrix& operator *=(T k) { rep (i, n_rows()) rep (j, n_cols()) (*this)(i, j) *= k; return *this; }
   Matrix& operator /=(T k) { rep (i, n_rows()) rep (j, n_cols()) (*this)(i, j) /= k; return *this; }
   friend Matrix operator *(const Matrix& a, const T b) { return Matrix(a) *= b; }
   friend Matrix operator *(const T a, const Matrix& b) { return Matrix(b) *= a; }
   friend Matrix operator /(const Matrix& a, const T b) { return Matrix(a) /= b; }

   // 単項演算子
   Matrix operator -() const { Matrix mat(n_rows(), n_cols()); rep (i, n_rows()) rep (j, n_cols()) mat(i, j) = -this->m[i][j]; return mat; }
   Matrix operator +() const { return *this; }

   // 累乗
   Matrix pow(int n) { return (*this) ^ n; }
   friend Matrix pow(const Matrix& mat, int n) { return mat.pow(n); }

   // 行列式 （T型が体であるときのみ対応）
   T det() {
      assert(n_rows() == n_cols());
      Matrix mat(*this);
      T ret = 1;
      rep (i, n_cols()) {
         int idx = -1;
         rep (j, i, n_cols()) {
            if (mat(j, i) != T(0)) idx = j;
         }
         if (idx == -1) return 0;
         if (i != idx) {
            ret *= -1;
            swap(mat[i], mat[idx]);
         }
         ret *= mat(i, i);
         T v = mat(i, i);
         rep (j, n_cols()) mat(i, j) /= v;
         rep (j, i + 1, n_cols()) {
            T a = mat(j, i);
            rep (k, n_cols()) mat(j, k) -= mat(i, k) * a;
         }
      }
      return ret;
   }
   friend T det(const Matrix& mat) { return mat.det(); }

   // 転置行列
   Matrix transposed() const {
      Matrix mat(n_cols(), n_rows());
      rep (i, n_rows()) {
         rep (j, n_cols()) {
            mat(j, i) = m[i][j];
         }
      }
      return mat;
   }
   friend T transposed(const Matrix& mat) { return mat.transposed(); }

   // 行のスライス
   Matrix selected_rows(const vector<int>& indices) {
      vector<vector<T>> acc;
      for (int i : indices) {
         acc.push_back(m[i]);
      }
      return Matrix(acc);
   }

   // 列のスライス
   Matrix selected_cols(const vector<int>& indices) {
      vector<vector<T>> acc;
      Matrix mt = transposed();
      for (int j : indices) {
         acc.push_back(mt[j]);
      }
      return Matrix(acc).transposed();
   }

   // 行列を横に合体させる
   //
   // ```
   // [1, 2; 3, 4].row_concat([5, 6, 7; 8, 9, 10]) # => [1, 2, 5, 6; 3, 4, 8, 9, 10]
   // ```
   Matrix row_concat(const Matrix& other) {
      assert(n_rows() == other.n_rows());
      Matrix ret(n_rows(), n_cols() + other.n_cols());
      const int w = n_cols();
      rep (i, n_rows()) {
         rep (j, w) ret(i, j) = m[i][j];
         rep (j, other.n_cols()) ret(i, w + j) = other[i][j];
      }
      return ret;
   }

   // 行列を縦に合体させる
   //
   // ```
   // [1, 2; 3, 4].row_concat([5, 6; 7, 8; 9, 10]) # => [1, 2; 3, 4; 5, 6; 7, 8; 9, 10]
   // ```
   Matrix col_concat(const Matrix& other) {
      assert(n_cols() == other.n_cols());
      Matrix ret(n_rows() + other.n_rows(), n_cols());
      const int h = n_rows();
      rep (i, h) {
         rep (j, n_cols()) ret(i, j) = m[i][j];
      }
      rep (i, other.n_rows()) {
         rep (j, other.n_cols()) ret(h + i, j) = other[i][j];
      }
      return ret;
   }

   // 入出力
   friend ostream& operator <<(ostream& os, const Matrix& mat){
      rep (i, mat.n_rows()) {
         rep (j, mat.n_cols()) {
            if (j != 0) os << ' ';
            os << mat(i, j);
         }
         if (i != mat.n_rows() - 1) os << '\n';
      }
      return os;
   }

private:
   vec<vec<T>> m;
};

using M = Matrix<mint>;

struct Parser {
   map<char, M> mp;
   vector<string> s;
   int line;
   string::const_iterator it;

   Parser() = default;

   Parser(const vector<string>& _s) : s(_s) {
   }

   void parse() {
      const int n = len(s);
      rep (i, 0, n) {
         line = i;
         it = s[i].begin();
         program();
      }
   }

   void program() {
      char var = *it++;
      assert(*it++ == '=');

      M res = expr();
      assert(*it++ == '.');

      mp[var] = res;
      cout << res << endl;
   }

   M expr() {
      M acc = term();
      while (*it == '+' || *it == '-') {
         char op = *it++;
         M other = term();
         if (op == '+') {
            acc += other;
         }
         else {
            acc -= other;
         }
      }
      return acc;
   }

   M term() {
      M acc = factor();
      while (*it == '*') {
         assert(*it++ == '*');
         M other = factor();
         if (isnumber(acc) && isnumber(other)) {
            acc *= other;
         }
         else if (isnumber(acc) && not isnumber(other)) {
            acc = acc(0, 0) * other;
         }
         else if (not isnumber(acc) && isnumber(other)) {
            acc *= other(0, 0);
         }
         else {
            assert(not isnumber(acc) && not isnumber(other));
            acc *= other;
         }
      }
      return acc;
   }

   M factor() {
      if (*it == '-') {
         assert(*it++ == '-');
         M ret = factor();
         return -ret;
      }
      return primary();
   }

   M primary() {
      M ret;
      if (isdigit(*it)) {
         mint val = inum();
         ret = M(1, 1, val);
      }
      else if (isalpha(*it)) {
         ret = mp[*it++];
      }
      else if (*it == '(') {
         assert(*it++ == '(');
         ret = expr();
         assert(*it++ == ')');
      }
      else {
         assert(*it == '[');
         ret = matrix();
      }

      while (*it == '(' || *it == '\'') {
         if (*it == '(') {
            assert(*it++ == '(');
            M is = expr();
            assert(*it++ == ',');
            M js = expr();
            assert(*it++ == ')');
            assert(is.n_rows() == 1);
            assert(js.n_rows() == 1);
            {
               vector<int> indices;
               rep (j, 0, is.n_cols()) {
                  indices.push_back(is(0, j).val() - 1);
               }
               ret = ret.selected_rows(indices);
            }
            {
               vector<int> indices;
               rep (j, 0, js.n_cols()) {
                  indices.push_back(js(0, j).val() - 1);
               }
               ret = ret.selected_cols(indices);
            }
         }
         else if (*it == '\'') {
            assert(*it++ == '\'');
            ret = ret.transposed();
         }
      }
      return ret;
   }

   M matrix() {
      assert(*it++ == '[');
      M row = row_seq();
      assert(*it++ == ']');
      return row;
   }

   M row_seq() {
      M acc = row();
      while (*it == ';') {
         assert(*it++ == ';');
         M other = row();
         acc = acc.col_concat(other);
      }
      return acc;
   }

   M row() {
      M acc = expr();
      while (*it == ' ') {
         assert(*it++ == ' ');
         M other = expr();
         acc = acc.row_concat(other);
      }
      return acc;
   }

   bool isnumber(const M& mat) {
      return mat.n_rows() == 1 && mat.n_cols() == 1;
   }

   mint inum() {
      mint ret = 0;
      for (; isdigit(*it); ++it) {
         ret = 10*ret + (*it - '0');
      }
      return ret;
   }
};

int32 main() {
   while (true) {
      auto n = sc.nextInt();
      if (!n) break;
      vector<string> s(n);
      for (string& si : s) si = sc.nextLine();
      Parser(s).parse();
      cout << "-----" << endl;
   }
}
accuracy: 1
time_ms: 10
memory_kb: 3608
final_rank: 4

code_snippet: #include <string.h>

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cfloat>
#include <chrono>
#include <ciso646>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define REP_OVERLOAD(arg1, arg2, arg3, arg4, NAME, ...) NAME
#define REP3(i, l, r, s)                                               \
    for (int i = int(l), rep3_r = int(r), rep3_s = int(s); i < rep3_r; \
         i += rep3_s)
#define REP2(i, l, r) REP3(i, l, r, 1)
#define REP1(i, n) REP2(i, 0, n)
#define rep(...) REP_OVERLOAD(__VA_ARGS__, REP3, REP2, REP1, )(__VA_ARGS__)
#define repin(i, l, r) for (int i = int(l), repin_r = int(r); i <= repin_r; ++i)

#define RREP_OVERLOAD(arg1, arg2, arg3, arg4, NAME, ...) NAME
#define RREP3(i, l, r, s)                                                      \
    for (int i = int(r) - 1, rrep3_l = int(l), rrep3_s = int(s); i >= rrep3_l; \
         i -= rrep3_s)
#define RREP2(i, l, r) RREP3(i, l, r, 1)
#define RREP1(i, n) RREP2(i, 0, n)
#define rrep(...) RREP_OVERLOAD(__VA_ARGS__, RREP3, RREP2, RREP1, )(__VA_ARGS__)
#define rrepin(i, l, r) \
    for (int i = int(r), rrepin_l = int(l); i >= rrepin_l; --i)


#include <algorithm>
#include <cassert>
#include <vector>

namespace rklib {

// a <- max(a, b)
template <class T>
bool chmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

// a <- min(a, b)
template <class T>
bool chmin(T &a, const T &b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

// if a < 0: a <- b
// else: a <- min(a, b)
template <class T>
bool chmin_non_negative(T &a, const T &b) {
    if (a < 0 || a > b) {
        a = b;
        return true;
    }
    return false;
}

// floor(num / den)
template <class T>
T div_floor(T num, T den) {
    if (den < 0) num = -num, den = -den;
    return num >= 0 ? num / den : (num + 1) / den - 1;
}

// ceil(num / den)
template <class T>
T div_ceil(T num, T den) {
    if (den < 0) num = -num, den = -den;
    return num <= 0 ? num / den : (num - 1) / den + 1;
}

namespace internal {

template <class T>
T remainder_count(T r, T b, T m) {
    return r / m * b + std::min(b, r % m);
}

}  // namespace internal

// Number of integer x s.t.
// - x in [l, r)
// - x mod m in [a, b)
template <class T>
T remainder_count(T l, T r, T a, T b, T m) {
    assert(l >= 0);
    assert(m >= 1);

    if (l >= r || a >= b) return 0;
    if (m <= a || b < 0) return 0;
    chmax(a, T(0));
    chmin(b, m);

    auto res = internal::remainder_count(r, b, m);
    if (l >= 1) res -= internal::remainder_count(l, b, m);
    if (a >= 1) res -= internal::remainder_count(r, a, m);
    if (l >= 1 && a >= 1) res += internal::remainder_count(l, a, m);

    return res;
}

}  // namespace rklib


using namespace std;
using namespace rklib;

using lint = long long;
using ulint = unsigned long long;
using pii = pair<int, int>;
using pll = pair<lint, lint>;



#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m < 2^31`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder


#include <assert.h>

#include <vector>

namespace rklib {

template <class T>
struct Matrix {
    std::vector<std::vector<T>> a;

    Matrix() : a(1, std::vector<T>(1, 0)) {}
    Matrix(int n, int m) : a(n, std::vector<T>(m, 0)) {}
    Matrix(int n) : a(n, std::vector<T>(n, 0)) {}

    int height() const { return a.size(); }
    int width() const { return a[0].size(); }

    inline const std::vector<T> &operator[](int i) const { return a[i]; }
    inline std::vector<T> &operator[](int i) { return a[i]; }

    static Matrix id(int n) {
        Matrix res(n);
        for (int i = 0; i < n; i++) res[i][i] = 1;
        return res;
    }

    Matrix &operator*=(const Matrix &b) {
        assert(width() == b.height());
        std::vector<std::vector<T>> c(height(), std::vector<T>(b.width()));
        for (int i = 0; i < height(); ++i) {
            for (int k = 0; k < b.height(); ++k) {
                for (int j = 0; j < b.width(); ++j) {
                    c[i][j] += a[i][k] * b[k][j];
                }
            }
        }
        a.swap(c);
        return *this;
    }

    Matrix pow(long long n) const {
        auto x = (*this), res = id(height());
        while (n) {
            if (n & 1) {
                res *= x;
                --n;
            } else {
                x *= x;
                n >>= 1;
            }
        }
        return res;
    }

    Matrix operator*(const Matrix &b) const { return Matrix(*this) *= b; }

    std::vector<T> operator*(const std::vector<T> &v) {
        assert(width() == (int)v.size());
        std::vector<T> res(height(), 0);
        for (int i = 0; i < height(); ++i) {
            for (int j = 0; j < width(); ++j) {
                res[i] += a[i][j] * v[j];
            }
        }
        return res;
    }

    Matrix transposed() {
        Matrix res(this->width(), this->height());
        for (size_t i = 0; i < this->height(); i++) {
            for (size_t j = 0; j < this->width(); j++) {
                res[j][i] = this->a[i][j];
            }
        }
        return res;
    }
};

template <class T>
std::pair<int, bool> gauss_jordan(Matrix<T> &a) {
    int rnk = 0;
    bool swp = false;
    for (int j = 0; j < a.width(); ++j) {
        int pivot = -1;
        for (int i = rnk; i < a.height(); ++i) {
            if (a[i][j] != 0) {
                pivot = i;
                break;
            }
        }
        if (pivot < 0) continue;
        swap(a[pivot], a[rnk]);
        if (pivot != rnk) swp ^= true;
        for (int i = 0; i < a.height(); ++i) {
            if (i != rnk && a[i][j] != 0) {
                auto coef = a[i][j] / a[rnk][j];
                for (int k = j; k < a.width(); ++k) {
                    a[i][k] -= a[rnk][k] * coef;
                }
            }
        }
        ++rnk;
    }
    return {rnk, swp};
}

template <class T>
T determinant(Matrix<T> a) {
    auto [rnk, swp] = gauss_jordan(a);
    if (rnk < a.height()) return 0;
    T res = 1;
    for (int i = 0; i < a.height(); ++i) res *= a[i][i];
    if (swp) res = -res;
    return res;
}

template <class T>
std::pair<std::vector<T>, std::vector<std::vector<T>>>
system_of_linear_equations(Matrix<T> a, const std::vector<T> &b) {
    assert(a.height() == (int)b.size());
    Matrix<T> aug(a.height(), a.width() + 1);
    for (int i = 0; i < a.height(); ++i) {
        for (int j = 0; j < a.width(); ++j) {
            aug[i][j] = a[i][j];
        }
        aug[i][a.width()] = b[i];
    }

    auto rnk = gauss_jordan(a).first, rnk_aug = gauss_jordan(aug).first;

    std::vector<T> solution;
    std::vector<std::vector<T>> kernel;
    if (rnk < rnk_aug) return {solution, kernel};

    solution.resize(a.width(), 0);
    std::vector<bool> used(a.width(), false);
    std::vector<int> pos(rnk);
    for (int i = 0; i < rnk; ++i) {
        for (int j = 0; j < a.width(); ++j) {
            if (aug[i][j] != 0) {
                solution[j] = aug[i][a.width()] / aug[i][j];
                used[j] = true;
                pos[i] = j;
                break;
            }
        }
    }
    for (int j = 0; j < a.width(); ++j) {
        if (!used[j]) {
            std::vector<T> v(a.width(), 0);
            v[j] = 1;
            for (int i = 0; i < rnk; ++i) {
                v[pos[i]] = -aug[i][j] / aug[i][pos[i]];
            }
            kernel.push_back(v);
        }
    }
    return {solution, kernel};
}

}  // namespace rklib


using mint = atcoder::modint;
using mat = Matrix<mint>;

mat var(string &s, int &idx);
mat expr(string &s, int &idx);
mat term(string &s, int &idx);
mat factor(string &s, int &idx);
mat primary(string &s, int &idx);
mat matrix(string &s, int &idx);
mat row_seq(string &s, int &idx);
mat row(string &s, int &idx);
mat inum(string &s, int &idx);

mat vars[26];

mat var(string &s, int &idx) {
    auto res = vars[s[idx] - 'A'];
    ++idx;
    return res;
}
mat expr(string &s, int &idx) {
    auto res = term(s, idx);
    while (idx < int(s.size()) && (s[idx] == '+' || s[idx] == '-')) {
        auto op = s[idx];
        ++idx;
        auto tmp = term(s, idx);
        if (op == '+') {
            rep(i, res.height()) rep(j, res.width()) res[i][j] += tmp[i][j];
        } else {
            rep(i, res.height()) rep(j, res.width()) res[i][j] -= tmp[i][j];
        }
    }
    return res;
}
mat term(string &s, int &idx) {
    auto res = factor(s, idx);
    while (idx < int(s.size()) && s[idx] == '*') {
        ++idx;
        auto tmp = factor(s, idx);
        if (res.height() == 1 && res.width() == 1) {
            auto coef = res[0][0];
            res = tmp;
            rep(i, res.height()) rep(j, res.width()) res[i][j] *= coef;
        } else if (tmp.height() == 1 && tmp.width() == 1) {
            auto coef = tmp[0][0];
            rep(i, res.height()) rep(j, res.width()) res[i][j] *= coef;
        } else {
            res = res * tmp;
        }
    }
    return res;
}
mat factor(string &s, int &idx) {
    if (s[idx] == '-') {
        ++idx;
        auto res = factor(s, idx);
        rep(i, res.height()) rep(j, res.width()) res[i][j] = -res[i][j];
        return res;
    }
    return primary(s, idx);
}
mat primary(string &s, int &idx) {
    mat res;
    if (isdigit(s[idx])) {
        res = inum(s, idx);
    } else if ('A' <= s[idx] && s[idx] <= 'Z') {
        res = var(s, idx);
    } else if (s[idx] == '[') {
        res = matrix(s, idx);
    } else {
        ++idx;
        res = expr(s, idx);
        ++idx;
    }
    while (idx < s.size() && (s[idx] == '\'' || s[idx] == '(')) {
        if (s[idx] == '\'') {
            ++idx;
            res = res.transposed();
        } else {
            ++idx;
            auto A = expr(s, idx);
            ++idx;
            auto B = expr(s, idx);
            ++idx;
            mat tmp(A.width(), B.width());
            rep(i, A.width()) rep(j, B.width()) {
                tmp[i][j] = res[A[0][i].val() - 1][B[0][j].val() - 1];
            }
            res = tmp;
        }
    }
    return res;
}
mat matrix(string &s, int &idx) {
    ++idx;
    auto res = row_seq(s, idx);
    ++idx;
    return res;
}
mat row_seq(string &s, int &idx) {
    auto res = row(s, idx);
    while (idx < int(s.size()) && s[idx] == ';') {
        ++idx;
        auto tmp = row(s, idx);
        mat res2(res.height() + tmp.height(), res.width());
        rep(j, res.width()) {
            rep(i, res.height()) res2[i][j] = res[i][j];
            rep(i, tmp.height()) res2[i + res.height()][j] = tmp[i][j];
        }
        res = res2;
    }
    return res;
}
mat row(string &s, int &idx) {
    auto res = expr(s, idx);
    while (idx < int(s.size()) && s[idx] == ' ') {
        ++idx;
        auto tmp = expr(s, idx);
        mat res2(res.height(), res.width() + tmp.width());
        rep(i, res.height()) {
            rep(j, res.width()) res2[i][j] = res[i][j];
            rep(j, tmp.width()) res2[i][j + res.width()] = tmp[i][j];
        }
        res = res2;
    }
    return res;
}
mat inum(string &s, int &idx) {
    mat res(1, 1);
    mint tmp = 0;
    while (idx < int(s.size()) && isdigit(s[idx])) {
        tmp = tmp * 10 + (s[idx] - '0');
        ++idx;
    }

    res[0][0] = tmp;
    return res;
}

int main() {
    mint::set_mod(32768);

    while (true) {
        string s;
        getline(cin, s);
        int n = stoi(s);
        if (n == 0) break;
        rep(_, n) {
            getline(cin, s);
            int idx = 0;

            auto c = s[idx];
            idx += 2;
            auto ans = expr(s, idx);
            vars[c - 'A'] = ans;

            rep(i, ans.height()) {
                rep(j, ans.width()) {
                    cout << ans[i][j].val();
                    if (j == ans.width() - 1) {
                        cout << "\n";
                    } else {
                        cout << " ";
                    }
                }
            }
        }
        puts("-----");
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3776
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)
#define ALL(x) x.begin(), x.end()
#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)
using namespace std;
random_device rnd;
mt19937 mt(rnd());
using ll = long long;
using lld = long double;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using PII = pair<int, int>;
const int IINF = 1 << 30;
const ll INF = 1ll << 60;
const ll MOD = 32768;

using Matrix = vector<vector<int>>;

string code;

void program(int &pos);
void assign(int &pos);
Matrix expr(int &pos);
Matrix term(int &pos);
Matrix factor(int &pos);
Matrix primary(int &pos);
Matrix indexed_primary(int &pos);
Matrix transposed_primary(int &pos);
Matrix matrix(int &pos);
Matrix row_seq(int &pos);
Matrix inum(int &pos);
int digit(int &pos);
map<char, Matrix> var;

void debug(int pos)
{
    cerr << pos << " " << code.size() << endl;
    rep(i, pos, code.size())
    {
        cout << code[i];
    }
    cout << endl;
}
void print(Matrix &mat)
{
    for (auto r : mat)
    {
        rep(j, r.size())
        {
            auto elem = r[j];
            cout << elem << (j == r.size() - 1 ? "" : " ");
        }
        cout << endl;
    }
}

void addsub(Matrix &a, Matrix &b, char op)
{
    assert(a.size() == b.size());
    assert(a[0].size() == b[0].size());
    rep(i, a.size())
    {
        rep(j, a[0].size())
        {

            a[i][j] += (op == '+' ? 1 : -1) * b[i][j];
            a[i][j] += MOD;
            a[i][j] %= MOD;
        }
    }
}
Matrix trans(Matrix &a)
{
    Matrix ret(a[0].size(), vector<int>(a.size()));
    rep(i, a.size()) rep(j, a[0].size())
    {
        ret[j][i] = a[i][j];
    }
    return ret;
}
Matrix mul(Matrix a, Matrix b)
{

    if (a[0].size() == b.size())
    {
        Matrix c(a.size(), vector<int>(b[0].size(), 0));
        rep(i, a.size())
        {
            rep(j, b[0].size())
            {
                rep(k, a[0].size())
                {
                    c[i][j] += a[i][k] * b[k][j];
                    c[i][j] %= MOD;
                }
            }
        }
        return c;
    }
    else if (a.size() == 1 && a[0].size() == 1)
    {
        Matrix c(b.size(), vector<int>(b[0].size(), 0));
        rep(i, b.size())
        {
            rep(j, b[0].size())
            {
                c[i][j] = b[i][j] * a[0][0];
                c[i][j] %= MOD;
            }
        }
        return c;
    }
    else
    {
        assert(b.size() == 1 && b[0].size() == 1);
        Matrix c(a.size(), vector<int>(a[0].size(), 0));
        rep(i, a.size())
        {
            rep(j, a[0].size())
            {
                c[i][j] = a[i][j] * b[0][0];
                c[i][j] %= MOD;
            }
        }
        return c;
    }
}

int digit(int &pos)
{
    assert(isdigit(code[pos]));
    return code[pos++] - '0';
}

Matrix inum(int &pos)
{
    Matrix ret(1);
    int num = 0;
    while (isdigit(code[pos]))
    {
        num = num * 10 + digit(pos);
    }
    ret[0].push_back(num);
    return ret;
}

void fill(Matrix &ret, Matrix mat, int r, int c)
{
    rep(i, mat.size())
    {
        rep(j, mat[0].size())
        {
            if (mat[i][j] != -1)
            {
                ret[r + i][c + j] = mat[i][j];
            }
        }
    }
}

void shrink(Matrix &mat)
{
    assert(!mat.back().empty());
    while (mat.back()[0] == -1)
    {
        mat.pop_back();
        assert(!mat.empty());
        assert(!mat.back().empty());
    }
    rep(i, mat.size())
    {
        assert(!mat[i].empty());
        while (mat[i].back() == -1)
        {
            mat[i].pop_back();
            assert(!mat[i].empty());
        }
    }
}

Matrix row_seq(int &pos)
{
    Matrix ret(128, vector<int>(128, -1));
    // debug(pos);
    Matrix m = expr(pos);
    // debug(pos);
    int r = 0, c = 0;
    int width = -1;
    fill(ret, m, r, c);
    while (ret[r][c] != -1)
        c++;
    //    debug(pos);

    while (code[pos] == ';' || code[pos] == ' ')
    {
        if (code[pos] == ' ')
        {
            pos++;
            // m = expr(pos);
            // fill(ret, m, r, c);
            // while (ret[r][c] != -1)
            //     c++;
        }
        else
        {
            pos++;
            if (width == -1)
                width = c;
            else
                assert(width == c);
            c = 0;
            r++;
            while (ret[r][c] != -1)
            {
                c++;
                if (c == width)
                {
                    c = 0;
                    r++;
                }
            }
        }

        m = expr(pos);
        fill(ret, m, r, c);
        while (ret[r][c] != -1)
            c++;
    }
    // print(ret);
    shrink(ret);
    // print(ret);
    return ret;
}

Matrix matrix(int &pos)
{
    assert(code[pos] == '[');
    pos++;
    auto ret = row_seq(pos);
    //    cerr << code[pos] << endl;
    assert(code[pos] == ']');
    pos++;
    return ret;
}

Matrix primary(int &pos)
{
    Matrix ret;
    if (isdigit(code[pos]))
    {
        ret = inum(pos);
    }
    else if (code[pos] == '[')
    {
        ret = matrix(pos);
    }
    else if (code[pos] == '(')
    {
        pos++;
        ret = expr(pos);
        assert(code[pos] == ')');
        pos++;
    }
    else
    {
        ret = var[code[pos]];
        pos++;
    }
    while (code[pos] == '(' || code[pos] == '\'')
    {

        if (code[pos] == '(')
        {
            pos++;
            auto rows = expr(pos);
            assert(code[pos] == ',');
            pos++;
            auto cols = expr(pos);
            assert(rows.size() == 1);
            assert(cols.size() == 1);
            assert(code[pos] == ')');
            pos++;
            Matrix tmp(128, vector<int>(128, -1));
            rep(i, rows[0].size())
            {
                rep(j, cols[0].size())
                {
                    tmp[i][j] = ret[rows[0][i] - 1][cols[0][j] - 1];
                }
            }
            ret = tmp;
            shrink(ret);
        }
        else if (code[pos] == '\'')
        {
            pos++;
            ret = trans(ret);
        }
    }

    return ret;
}

Matrix expr(int &pos)
{
    Matrix ret = term(pos);
    while (code[pos] == '+' || code[pos] == '-')
    {
        char op = code[pos];
        pos++;
        Matrix m = term(pos);
        addsub(ret, m, op);
    }
    return ret;
}

Matrix term(int &pos)
{
    Matrix ret = factor(pos);
    while (code[pos] == '*')
    {
        pos++;
        Matrix m = factor(pos);
        ret = mul(ret, m);
    }
    return ret;
}

Matrix factor(int &pos)
{
    if (code[pos] == '-')
    {
        pos++;
        Matrix ret = factor(pos);
        rep(i, ret.size())
        {
            rep(j, ret[0].size())
            {
                ret[i][j] = MOD - ret[i][j];
            }
        }
        return ret;
    }
    return primary(pos);
}

void program(int &pos)
{
    while (pos < code.size())
    {
        assign(pos);
    }
}

void assign(int &pos)
{
    char v = code[pos];
    pos++;
    assert(code[pos] == '=');
    pos++;
    var[v] = expr(pos);
    print(var[v]);
    //  debug(pos);
    assert(code[pos] == '.');
    pos++;
}

void solve(int n)
{
    code = "";
    rep(i, n)
    {
        string s;
        getline(cin, s);
        code += s;
    }
    // cerr << code << endl;
    int pos = 0;
    program(pos);
    cout << "-----" << endl;
}

int main()
{
    int n;
    while (cin >> n, cin.ignore(), n)
    {
        solve(n);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3988
final_rank: 16

code_snippet: /*
　　　∫ ∫ ∫
　　　ノヽ
　　（＿　 ）
　（＿　　　 ）
（＿＿＿＿＿＿ ）
　ヽ(´･ω･)ﾉ　
　　 |　 /
　　 UU
*/
#pragma region macro
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
#include <vector>
#include <cassert>
#include <cmath>
#include <utility>
#include <tuple>
#include <map>
#include <set>
#include <deque>
#include <queue>
typedef long long int64;
using namespace std;
typedef vector<int> vi;
const int MOD = 1<<15;
const int64 INF = 1LL << 62;
const int inf = 1<<30;
const char bn = '\n';
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
#define REP(i, n) for (int i = 0; i < (n); i++)
#define ALL(obj) (obj).begin(), (obj).end() //コンテナじゃないと使えない!!
#define debug(x) cerr << #x << ": " << (x) << "\n";
#define mp make_pair
template <typename T>
ostream& operator<<(ostream& os, const vector<T> &V){
    int N = V.size();
    REP(i,N){
        os << V[i];
        if (i!=N-1) os << " ";
    }
    os << "\n";
    return os;
}
template <typename T,typename S>
ostream& operator<<(ostream& os, pair<T,S> const&P){
    os << "(";
    os << P.first;
    os << " , ";
    os << P.second;
    os << ")";
    return os;
}
template <typename T,typename S,typename U>
ostream& operator<<(ostream& os, tuple<T,S,U> const& P){
    os << "(";
    os << get<0>(P);
    os << ", ";
    os << get<1>(P);
    os << ", ";
    os << get<2>(P);
    os << ")";
    return os;
}
template <typename T>
ostream& operator<<(ostream& os, set<T> &S){
    auto it=S.begin();
    while(it!=S.end()){
        os << *it;
        os << " ";
        it++;
    }
    os << "\n";
    return os;
}
template <typename T>
ostream& operator<<(ostream& os, deque<T> &q){
    for(auto it=q.begin();it<q.end();it++){
        os<<*it;
        os<<" ";
    }
    os<<endl;
    return os;
}
template <typename T,typename S>
ostream& operator<<(ostream& os, map<T,S> const&M){
    for(auto e:M){
        os<<e;
    }
    os<<endl;
    return os;
}
vector<pair<int,int>> dxdy = {mp(0,1),mp(1,0),mp(-1,0),mp(0,-1)};
#pragma endregion
//fixed<<setprecision(10)<<ans<<endl;


int64 pow(int a,int b,int mod){
    vector<bool> bit;
    for(b=b;b>0;b>>=1){
        bit.push_back(b&1);
    }
    vector<int64> fac(bit.size()); fac[0] = a;
    int64 res = 1;
    for(int i=1;i<bit.size();i++){
        fac[i] = (fac[i-1] * fac[i-1])%mod;
    }
    for(int i=0;i<bit.size();i++){
        if(bit[i]) res*=fac[i];
        res%=mod;
    }
    return res;
}


//mint
struct mint {
    int64 x;
    mint(int64 x=0):x((x+2*MOD)%MOD){}
    mint& operator+=(const mint a) {
        if ((x += a.x) >= MOD) x -= MOD;
        return *this;
    }
    mint& operator-=(const mint a) {
        if ((x += MOD-a.x) >= MOD) x -= MOD;
        return *this;
    }
    mint& operator*=(const mint a) {
        (x *= a.x) %= MOD;
        return *this;
    }
    mint operator+(const mint a) const {
        mint res(*this);
        return res+=a;
    }
    mint operator-(const mint a) const {
        mint res(*this);
        return res-=a;
    }
    mint operator*(const mint a) const {
        mint res(*this);
        return res*=a;
    }
    mint pow(int64 t) const {
        if (!t) return 1;
        mint a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }

    // for prime MOD
    mint inv() const {
        return pow(MOD-2);
    }
    mint& operator/=(const mint a) {
        return (*this) *= a.inv();
    }
    mint operator/(const mint a) const {
        mint res(*this);
        return res/=a;
    }
};
ostream& operator<<(ostream& os, mint a){
    os << a.x;
    return os;
}

template <typename T>
struct Matrix{
    vector<vector<T>> matrix_data;
    Matrix(){}
    Matrix(const vector<vector<T>>& matrix_data):matrix_data(matrix_data){}
    Matrix(const T& val):matrix_data(vector<vector<T>>(1, vector<T>(1, val))){} //1*1の行列

    //単位行列
    Matrix<T> Identity(size_t N){
        vector<vector<T>> res(N,vector<T>(N,0));
        for(size_t i=0; i<N; i++) res[i][i]=1;
        return Matrix<T>(res);
    }

    //累乗O(N^3 log k)
    Matrix<T> power(int64 k){
        Matrix<T> res = Matrix::Identity(matrix_data.size());
        Matrix<T> tmp = *this;

        while(k){
            if(k&1){res *= tmp;}
            tmp *= tmp;
            k >>= 1LL;
        }
        return res;
    }

    void add_row(Matrix<T> const& A){
        assert(A.matrix_data[0].size() == matrix_data[0].size());
        
        for(auto row:A.matrix_data){
            matrix_data.emplace_back(row);
        }
    }

    void add_column(Matrix<T> const& A){
        assert(A.matrix_data.size() == matrix_data.size());
        
        REP(i, A.matrix_data.size()){
            for(auto v:A.matrix_data[i]){
                matrix_data[i].emplace_back(v);
            }        
        }
    }

    Matrix<T> transpose(){
        vector<vector<T>> res(matrix_data[0].size(), vector<T>(matrix_data.size()));
        REP(i, matrix_data.size()){
            REP(j, matrix_data[0].size()){
                res[j][i] = matrix_data[i][j];
            }
        }

        return Matrix<T>(res);
    }


};

template <typename T>
Matrix<T> operator+(const Matrix<T>& mat_a, const Matrix<T>& mat_b){
    assert(mat_a.matrix_data.size() == mat_b.matrix_data.size());
    assert(mat_a.matrix_data[0].size() == mat_b.matrix_data[0].size());
    size_t A = mat_a.matrix_data.size();
    size_t B = mat_b.matrix_data[0].size();

    Matrix<T> res = mat_a;
    
    for(size_t i=0; i<A; i++){
        for(size_t j=0; j<B; j++){
            res.matrix_data[i][j] += mat_b.matrix_data[i][j];
        }
    }

    return res;
}

template <typename T>
Matrix<T>& operator+=(Matrix<T>& mat_a, Matrix<T>& mat_b){
    mat_a = mat_a+mat_b;
    return mat_a;
}

template <typename T>
Matrix<T> operator-(const Matrix<T>& mat_a, const Matrix<T>& mat_b){
    assert(mat_a.matrix_data.size() == mat_b.matrix_data.size());
    assert(mat_a.matrix_data[0].size() == mat_b.matrix_data[0].size());
    size_t A = mat_a.matrix_data.size();
    size_t B = mat_b.matrix_data[0].size();

    Matrix<T> res = mat_a;
    
    for(size_t i=0; i<A; i++){
        for(size_t j=0; j<B; j++){
            res.matrix_data[i][j] -= mat_b.matrix_data[i][j];
        }
    }

    return res;
}

template <typename T>
Matrix<T>& operator-=(Matrix<T>& mat_a, Matrix<T>& mat_b){
    mat_a = mat_a-mat_b;
    return mat_a;
}

template <typename T>
bool is_scalar_(Matrix<T> const& A){
    return A.matrix_data.size() == 1 and A.matrix_data[0].size() == 1;
}

template <typename T>
Matrix<T> operator*(const Matrix<T>& mat_a, const Matrix<T>& mat_b){
    if( is_scalar_(mat_a) ){
        return mat_a.matrix_data[0][0].x * mat_b;
    }else if( is_scalar_(mat_b) ){
        return mat_b.matrix_data[0][0].x * mat_a;

    }
    size_t A = mat_a.matrix_data.size();
    size_t B = mat_b.matrix_data.size();
    assert(B > 0);
    size_t C = mat_b.matrix_data[0].size();

    Matrix<T> res(vector<vector<T>>(A,vector<T>(C,0)));
    
    for(size_t i=0; i<A; i++){
        assert(mat_a.matrix_data[i].size() == B);
        for(size_t j=0; j<C; j++){
            for(size_t k=0; k<B; k++){
                res.matrix_data[i][j] += mat_a.matrix_data[i][k] * mat_b.matrix_data[k][j];
            }
        }
    }

    return res;
}

template <typename T>
Matrix<T> operator*(const int& val, const Matrix<T>& mat_a){
    Matrix<T> res = mat_a;
    for(auto&& row: res.matrix_data){
        for(auto&& a:row) a *= val;
    }
    
    return res;
}

template <typename T>
Matrix<T>& operator*=(Matrix<T>& mat_a, Matrix<T>& mat_b){
    mat_a = mat_a*mat_b;
    return mat_a;
}

template <typename T>
ostream& operator<<(ostream& os, const Matrix<T>& M){
    REP(i,M.matrix_data.size()){
        REP(j,M.matrix_data[0].size()){
            os << M.matrix_data[i][j];
            if(j!=M.matrix_data[0].size()-1) os<<" ";
        }
        os << "\n";
    }
    return os;
}



map<char, Matrix<mint>> matrix_dict;

// 構文解析
/*
    構文解析でよくあるバグは次の二つです。
    - begin++をし忘れる
    - getlineとcinの混合
*/


typedef string::const_iterator State;
class ParseError {};

// beginがexpectedを指していたらbeginを一つ進める。
void consume(State &begin, char expected) {
    if (*begin == expected) {
        begin++;
    } else {
        cerr << "Expected '" << expected << "' but got '" << *begin << "'"
            << endl;
        cerr << "Rest string is '";
        while (*begin) {
            cerr << *begin++;
        }
        cerr << "'" << endl;
        throw ParseError();
    }
}
void print_rest_string(State begin){
    cerr << "Rest string is '";
    while (*begin) {
        cerr << *begin++;
    }
    cerr << "'" << endl;
}

bool is_capital(char C){
    return 'A' <= C and C <= 'Z';
}

Matrix<mint> expression(State &begin);
Matrix<mint> term(State &begin);
Matrix<mint> factor(State &begin);
Matrix<mint> primary(State &begin);
Matrix<mint> matrix(State &begin);
Matrix<mint> row(State &begin);
Matrix<mint> number(State &begin);

// 四則演算の式をパースして、その評価結果を返す。
Matrix<mint> expression(State &begin){
    Matrix<mint> res = term(begin);

    while(true){
        if(*begin == '+'){
            consume(begin, '+');
            auto tmp = term(begin);
            res += tmp;
        }else if(*begin == '-'){
            consume(begin, '-');
            auto tmp = term(begin);
            res -= tmp;
        }else{
            break;
        }
    }

    return res;
}

// 乗算除算の式をパースして、その評価結果を返す。
Matrix<mint> term(State &begin){
    Matrix<mint> res = factor(begin);
    
    while(true){
        if(*begin == '*'){
            consume(begin, '*');
            auto tmp = factor(begin);
            res *= tmp;
        }else{
            break;
        }
    }

    return res;
}

Matrix<mint> factor(State &begin){
    Matrix<mint> res;
    if(*begin == '-'){
        consume(begin, '-');
        auto tmp = factor(begin);
        res = (-1) * tmp ;
    }else{
        res = primary(begin);
    }
    return res;
}

Matrix<mint> primary(State &begin){
    Matrix<mint> res;
    if( isdigit(*begin) ){
        res = number(begin);
    }else if( is_capital(*begin) ){
        res = matrix_dict[*begin++];
    }else if( *begin == '[' ){
        res = matrix(begin);
    }else if( *begin == '(' ){
        consume(begin, '(');
        res = expression(begin);
        consume(begin, ')');
    }else{
        assert(false);
    }

    while(true){
        if(*begin == '('){
            consume(begin, '(');
            Matrix<mint> expr1 = expression(begin);
            consume(begin, ',');
            Matrix<mint> expr2 = expression(begin);
            consume(begin, ')');

            assert(expr1.matrix_data.size()==1);
            assert(expr2.matrix_data.size()==1);

            vector<vector<mint>> res_vec(expr1.matrix_data[0].size(), vector<mint>(expr2.matrix_data[0].size(), 0 ) );
            REP(i, expr1.matrix_data[0].size()){
                REP(j, expr2.matrix_data[0].size()){
                    res_vec[i][j] = res.matrix_data[ expr1.matrix_data[0][i].x-1 ][ expr2.matrix_data[0][j].x-1 ];
                }
            }
            res = Matrix<mint>( res_vec );
        }else if(*begin == '\''){
            consume(begin, '\'');
            res = res.transpose();
        }else break;

    }
    return res;
}

Matrix<mint> matrix(State &begin){
    consume(begin, '[');

    Matrix<mint> res = row(begin);

    while(true){
        if(*begin == ';'){
            consume(begin, ';');
            res.add_row( row(begin) );
        }else break;
    }

    consume(begin, ']');
    return res;
}

Matrix<mint> row(State &begin){
    Matrix<mint> res = expression(begin);

    while(true){
        if(*begin == ' '){
            consume(begin, ' ');
            res.add_column( expression(begin) );
        }else break;
    }

    return res;
}

// 数字の列をパースして、その数を返す。
Matrix<mint> number(State &begin){
    int val = 0;
    while(isdigit(*begin)){
        val *= 10;
        val += *begin - '0';
        begin++;
    }

    Matrix<mint> res(val);
    return res;
}

void solve(string S){
    State begin = S.begin();
    char var = *begin++;
    consume(begin, '=');

    Matrix<mint> ans = expression(begin);
    consume(begin, '.');
    matrix_dict[var] = ans;
    cout << ans;
}


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int N;
    string tmp;
    while(getline(cin, tmp)){
        N = stoi(tmp);
        if(N==0) break;
        REP(_, N){
            string S; getline(cin,S);
            // debug(S)
            solve(S);
        }
        cout << "-----" << endl;
    }
    
}
accuracy: 1
time_ms: 10
memory_kb: 4008
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=205,INF=1<<30;

//modintのみ

// from: https://gist.github.com/yosupo06/ddd51afb727600fd95d9d8ad6c3c80c9
// (based on AtCoder STL)

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {
    
    namespace internal {
        
#ifndef _MSC_VER
        template <class T>
        using is_signed_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value ||
        std::is_same<T, __int128>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int128 =
        typename std::conditional<std::is_same<T, __uint128_t>::value ||
        std::is_same<T, unsigned __int128>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using make_unsigned_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value,
        __uint128_t,
        unsigned __int128>;
        
        template <class T>
        using is_integral = typename std::conditional<std::is_integral<T>::value ||
        is_signed_int128<T>::value ||
        is_unsigned_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                         std::is_signed<T>::value) ||
        is_signed_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int =
        typename std::conditional<(is_integral<T>::value &&
                                   std::is_unsigned<T>::value) ||
        is_unsigned_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using to_unsigned = typename std::conditional<
        is_signed_int128<T>::value,
        make_unsigned_int128<T>,
        typename std::conditional<std::is_signed<T>::value,
        std::make_unsigned<T>,
        std::common_type<T>>::type>::type;
        
#else
        
        template <class T> using is_integral = typename std::is_integral<T>;
        
        template <class T>
        using is_signed_int =
        typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int =
        typename std::conditional<is_integral<T>::value &&
        std::is_unsigned<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using to_unsigned = typename std::conditional<is_signed_int<T>::value,
        std::make_unsigned<T>,
        std::common_type<T>>::type;
        
#endif
        
        template <class T>
        using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
        
        template <class T>
        using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
        
        template <class T> using to_unsigned_t = typename to_unsigned<T>::type;
        
    }  // namespace internal
    
}  // namespace atcoder

#include <utility>

namespace atcoder {
    
    namespace internal {
        
        constexpr long long safe_mod(long long x, long long m) {
            x %= m;
            if (x < 0) x += m;
            return x;
        }
        
        struct barrett {
            unsigned int _m;
            unsigned long long im;
            
            barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}
            
            unsigned int umod() const { return _m; }
            
            unsigned int mul(unsigned int a, unsigned int b) const {
                
                unsigned long long z = a;
                z *= b;
#ifdef _MSC_VER
                unsigned long long x;
                _umul128(z, im, &x);
#else
                unsigned long long x =
                (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
                unsigned int v = (unsigned int)(z - x * _m);
                if (_m <= v) v += _m;
                return v;
            }
        };
        
        constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
            if (m == 1) return 0;
            unsigned int _m = (unsigned int)(m);
            unsigned long long r = 1;
            unsigned long long y = safe_mod(x, m);
            while (n) {
                if (n & 1) r = (r * y) % _m;
                y = (y * y) % _m;
                n >>= 1;
            }
            return r;
        }
        
        constexpr bool is_prime_constexpr(int n) {
            if (n <= 1) return false;
            if (n == 2 || n == 7 || n == 61) return true;
            if (n % 2 == 0) return false;
            long long d = n - 1;
            while (d % 2 == 0) d /= 2;
            for (long long a : {2, 7, 61}) {
                long long t = d;
                long long y = pow_mod_constexpr(a, t, n);
                while (t != n - 1 && y != 1 && y != n - 1) {
                    y = y * y % n;
                    t <<= 1;
                }
                if (y != n - 1 && t % 2 == 0) {
                    return false;
                }
            }
            return true;
        }
        template <int n> constexpr bool is_prime = is_prime_constexpr(n);
        
        constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
            a = safe_mod(a, b);
            if (a == 0) return {b, 0};
            
            long long s = b, t = a;
            long long m0 = 0, m1 = 1;
            
            while (t) {
                long long u = s / t;
                s -= t * u;
                m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b
                
                
                auto tmp = s;
                s = t;
                t = tmp;
                tmp = m0;
                m0 = m1;
                m1 = tmp;
            }
            if (m0 < 0) m0 += b / s;
            return {s, m0};
        }
        
        constexpr int primitive_root_constexpr(int m) {
            if (m == 2) return 1;
            if (m == 167772161) return 3;
            if (m == 469762049) return 3;
            if (m == 754974721) return 11;
            if (m == 998244353) return 3;
            int divs[20] = {};
            divs[0] = 2;
            int cnt = 1;
            int x = (m - 1) / 2;
            while (x % 2 == 0) x /= 2;
            for (int i = 3; (long long)(i)*i <= x; i += 2) {
                if (x % i == 0) {
                    divs[cnt++] = i;
                    while (x % i == 0) {
                        x /= i;
                    }
                }
            }
            if (x > 1) {
                divs[cnt++] = x;
            }
            for (int g = 2;; g++) {
                bool ok = true;
                for (int i = 0; i < cnt; i++) {
                    if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                        ok = false;
                        break;
                    }
                }
                if (ok) return g;
            }
        }
        template <int m> constexpr int primitive_root = primitive_root_constexpr(m);
        
    }  // namespace internal
    
}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {
    
    namespace internal {
        
        struct modint_base {};
        struct static_modint_base : modint_base {};
        
        template <class T> using is_modint = std::is_base_of<modint_base, T>;
        template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;
        
    }  // namespace internal
    
    template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
    struct static_modint : internal::static_modint_base {
        using mint = static_modint;
        
    public:
        static constexpr int mod() { return m; }
        static mint raw(int v) {
            mint x;
            x._v = v;
            return x;
        }
        
        static_modint() : _v(0) {}
        template <class T, internal::is_signed_int_t<T>* = nullptr>
        static_modint(T v) {
            long long x = (long long)(v % (long long)(umod()));
            if (x < 0) x += umod();
            _v = (unsigned int)(x);
        }
        template <class T, internal::is_unsigned_int_t<T>* = nullptr>
        static_modint(T v) {
            _v = (unsigned int)(v % umod());
        }
        static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }
        
        unsigned int val() const { return _v; }
        
        mint& operator++() {
            _v++;
            if (_v == umod()) _v = 0;
            return *this;
        }
        mint& operator--() {
            if (_v == 0) _v = umod();
            _v--;
            return *this;
        }
        mint operator++(int) {
            mint result = *this;
            ++*this;
            return result;
        }
        mint operator--(int) {
            mint result = *this;
            --*this;
            return result;
        }
        
        mint& operator+=(const mint& rhs) {
            _v += rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator-=(const mint& rhs) {
            _v -= rhs._v;
            if (_v >= umod()) _v += umod();
            return *this;
        }
        mint& operator*=(const mint& rhs) {
            unsigned long long z = _v;
            z *= rhs._v;
            _v = (unsigned int)(z % umod());
            return *this;
        }
        mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
        
        mint operator+() const { return *this; }
        mint operator-() const { return mint() - *this; }
        
        mint pow(long long n) const {
            assert(0 <= n);
            mint x = *this, r = 1;
            while (n) {
                if (n & 1) r *= x;
                x *= x;
                n >>= 1;
            }
            return r;
        }
        mint inv() const {
            if (prime) {
                assert(_v);
                return pow(umod() - 2);
            } else {
                auto eg = internal::inv_gcd(_v, m);
                assert(eg.first == 1);
                return eg.second;
            }
        }
        
        friend mint operator+(const mint& lhs, const mint& rhs) {
            return mint(lhs) += rhs;
        }
        friend mint operator-(const mint& lhs, const mint& rhs) {
            return mint(lhs) -= rhs;
        }
        friend mint operator*(const mint& lhs, const mint& rhs) {
            return mint(lhs) *= rhs;
        }
        friend mint operator/(const mint& lhs, const mint& rhs) {
            return mint(lhs) /= rhs;
        }
        friend bool operator==(const mint& lhs, const mint& rhs) {
            return lhs._v == rhs._v;
        }
        friend bool operator!=(const mint& lhs, const mint& rhs) {
            return lhs._v != rhs._v;
        }
        
    private:
        unsigned int _v;
        static constexpr unsigned int umod() { return m; }
        static constexpr bool prime = internal::is_prime<m>;
    };
    
    template <int id> struct dynamic_modint : internal::modint_base {
        using mint = dynamic_modint;
        
    public:
        static int mod() { return (int)(bt.umod()); }
        static void set_mod(int m) {
            assert(1 <= m);
            bt = internal::barrett(m);
        }
        static mint raw(int v) {
            mint x;
            x._v = v;
            return x;
        }
        
        dynamic_modint() : _v(0) {}
        template <class T, internal::is_signed_int_t<T>* = nullptr>
        dynamic_modint(T v) {
            long long x = (long long)(v % (long long)(mod()));
            if (x < 0) x += mod();
            _v = (unsigned int)(x);
        }
        template <class T, internal::is_unsigned_int_t<T>* = nullptr>
        dynamic_modint(T v) {
            _v = (unsigned int)(v % mod());
        }
        dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }
        
        unsigned int val() const { return _v; }
        
        mint& operator++() {
            _v++;
            if (_v == umod()) _v = 0;
            return *this;
        }
        mint& operator--() {
            if (_v == 0) _v = umod();
            _v--;
            return *this;
        }
        mint operator++(int) {
            mint result = *this;
            ++*this;
            return result;
        }
        mint operator--(int) {
            mint result = *this;
            --*this;
            return result;
        }
        
        mint& operator+=(const mint& rhs) {
            _v += rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator-=(const mint& rhs) {
            _v += mod() - rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator*=(const mint& rhs) {
            _v = bt.mul(_v, rhs._v);
            return *this;
        }
        mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
        
        mint operator+() const { return *this; }
        mint operator-() const { return mint() - *this; }
        
        mint pow(long long n) const {
            assert(0 <= n);
            mint x = *this, r = 1;
            while (n) {
                if (n & 1) r *= x;
                x *= x;
                n >>= 1;
            }
            return r;
        }
        mint inv() const {
            auto eg = internal::inv_gcd(_v, mod());
            assert(eg.first == 1);
            return eg.second;
        }
        
        friend mint operator+(const mint& lhs, const mint& rhs) {
            return mint(lhs) += rhs;
        }
        friend mint operator-(const mint& lhs, const mint& rhs) {
            return mint(lhs) -= rhs;
        }
        friend mint operator*(const mint& lhs, const mint& rhs) {
            return mint(lhs) *= rhs;
        }
        friend mint operator/(const mint& lhs, const mint& rhs) {
            return mint(lhs) /= rhs;
        }
        friend bool operator==(const mint& lhs, const mint& rhs) {
            return lhs._v == rhs._v;
        }
        friend bool operator!=(const mint& lhs, const mint& rhs) {
            return lhs._v != rhs._v;
        }
        
    private:
        unsigned int _v;
        static internal::barrett bt;
        static unsigned int umod() { return bt.umod(); }
    };
    template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;
    
    using modint998244353 = static_modint<998244353>;
    using modint1000000007 = static_modint<1000000007>;
    using modint = dynamic_modint<-1>;
    
    namespace internal {
        
        template <class T>
        using is_static_modint = std::is_base_of<internal::static_modint_base, T>;
        
        template <class T>
        using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;
        
        template <class> struct is_dynamic_modint : public std::false_type {};
        template <int id>
        struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};
        
        template <class T>
        using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;
        
    }  // namespace internal
    
}  // namespace atcoder

using mint=atcoder::modint;

using mat=vector<vector<mint>>;
using vec=vector<mint>;

mat TEN;

mat add(mat &a,mat &b){
    assert(si(a)==si(b));
    assert(si(a[0])==si(b[0]));
    mat c(si(a),vec(si(a[0])));
    for(int i=0;i<si(c);i++){
        for(int j=0;j<si(c[0]);j++){
            c[i][j]=a[i][j]+b[i][j];
        }
    }
    return c;
}

mat sub(mat &a,mat &b){
    assert(si(a)==si(b));
    assert(si(a[0])==si(b[0]));
    mat c(si(a),vec(si(a[0])));
    for(int i=0;i<si(c);i++){
        for(int j=0;j<si(c[0]);j++){
            c[i][j]=a[i][j]-b[i][j];
        }
    }
    return c;
}

mat mul(mat &a,mat &b){
    if(si(a[0])==si(b)){
        mat c(si(a),vec(si(b[0])));
        for(int i=0;i<si(c);i++){
            for(int j=0;j<si(c[0]);j++){
                for(int k=0;k<si(a[0]);k++){
                    c[i][j]+=a[i][k]*b[k][j];
                }
            }
        }
        return c;
    }else if(si(b)==1&&si(b[0])==1){
        mat c(si(a),vec(si(a[0])));
        for(int i=0;i<si(c);i++){
            for(int j=0;j<si(c[0]);j++){
                c[i][j]=a[i][j]*b[0][0];
            }
        }
        return c;
    }else if(si(a)==1&&si(a[0])==1){
        mat c(si(b),vec(si(b[0])));
        for(int i=0;i<si(c);i++){
            for(int j=0;j<si(c[0]);j++){
                c[i][j]=b[i][j]*a[0][0];
            }
        }
        return c;
    }else{
        assert(false);
        return TEN;
    }
}

mat neg(mat &a){
    mat c(si(a),vec(si(a[0])));
    for(int i=0;i<si(c);i++){
        for(int j=0;j<si(c[0]);j++){
            c[i][j]=-a[i][j];
        }
    }
    return c;
}

map<char,mat> MA;
string S;

mat assignment(int &j);
char var(int &j);
mat var2(int &j);
mat expr(int &j);
mat term(int &j);
mat factor(int &j);
mat primary(int &j);
mat primary_sub(int &j);
mat matrix(int &j);
mat row_seq(int &j);
mat row(int &j);
mat inum(int &j);
mat digit(int &j);

mat assignment(int &j){
    char c=var(j);
    assert(S[j]=='=');
    j++;
    auto res=expr(j);
    assert(S[j]=='.');
    return MA[c]=res;
}

char var(int &j){
    char res=S[j];
    j++;
    return res;
}

mat var2(int &j){
    char c=S[j];
    assert(MA.count(c));
    j++;
    return MA[c];
}

mat expr(int &j){
    auto res=term(j);
    while(j<si(S)){
        char c=S[j];
        if(c=='+'){
            j++;
            auto X=term(j);
            res=add(res,X);
        }else if(c=='-'){
            j++;
            auto X=term(j);
            res=sub(res,X);
        }else{
            break;
        }
    }
    return res;
}

mat term(int &j){
    auto res=factor(j);
    while(j<si(S)){
        char c=S[j];
        if(c=='*'){
            j++;
            auto X=factor(j);
            res=mul(res,X);
        }else{
            break;
        }
    }
    return res;
}

mat factor(int &j){
    if(S[j]=='-'){
        j++;
        auto res=factor(j);
        return neg(res);
    }else{
        return primary(j);
    }
}

mat primary(int &j){
    auto res=primary_sub(j);
    while(j<si(S)){
        if(S[j]=='('){
            j++;
            auto H=expr(j);
            assert(S[j]==',');
            j++;
            auto W=expr(j);
            assert(S[j]==')');
            j++;
            mat X(si(H[0]),vec(si(W[0])));
            for(int h=0;h<si(H[0]);h++){
                for(int w=0;w<si(W[0]);w++){
                    X[h][w]=res[H[0][h].val()-1][W[0][w].val()-1];
                }
            }
            res=X;
        }else if(S[j]=='\''){
            j++;
            mat X(si(res[0]),vec(si(res)));
            for(int h=0;h<si(res);h++){
                for(int w=0;w<si(res[0]);w++){
                    X[w][h]=res[h][w];
                }
            }
            res=X;
        }else{
            break;
        }
    }
    
    return res;
}

mat primary_sub(int &j){
    if('0'<=S[j]&&S[j]<='9'){
        return inum(j);
    }else if('A'<=S[j]&&S[j]<='Z'){
        return var2(j);
    }else if(S[j]=='['){
        return matrix(j);
    }else if(S[j]=='('){
        j++;
        auto res=expr(j);
        assert(S[j]==')');
        j++;
        return res;
    }else{
        assert(false);
        return TEN;
    }
}

mat matrix(int &j){
    j++;
    auto res=row_seq(j);
    assert(S[j]==']');
    j++;
    return res;
}

mat row_seq(int &j){
    auto res=row(j);
    while(j<si(S)){
        if(S[j]==';'){
            j++;
            auto X=row(j);
            for(int h=0;h<si(X);h++) res.push_back(X[h]);
        }else break;
    }
    return res;
}

mat row(int &j){
    auto res=expr(j);
    while(j<si(S)){
        if(S[j]==' '){
            j++;
            auto X=expr(j);
            for(int h=0;h<si(X);h++){
                for(int w=0;w<si(X[h]);w++){
                    res[h].push_back(X[h][w]);
                }
            }
        }else{
            break;
        }
    }
    return res;
}

mat inum(int &j){
    mat res=digit(j);
    while(j<si(S)){
        if('0'<=S[j]&&S[j]<='9'){
            res=mul(res,TEN);
            auto X=digit(j);
            res=add(res,X);
        }else{
            break;
        }
    }
    return res;
}

mat digit(int &j){
    mint a=S[j]-'0';
    mat res={{a}};
    j++;
    return res;
}

int main() {
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    mint::set_mod(32768);
    
    TEN.push_back({});
    TEN.back().push_back(10);
    
    while(1){
        string N;
        getline(cin,N);
        if(N=="0") break;
        int NN=stoi(N);
        MA.clear();
        for(int i=0;i<NN;i++){
            getline(cin,S);
            int j=0;
            auto res=assignment(j);
            for(int h=0;h<si(res);h++){
                for(int w=0;w<si(res[h]);w++){
                    if(w) cout<<" ";
                    cout<<res[h][w].val();
                }
                cout<<"\n";
            }
        }
        
        cout<<"-----\n";
    }
    
}
accuracy: 1
time_ms: 10
memory_kb: 3672
final_rank: 7

code_snippet: #include <bits/stdc++.h>

using namespace std;

template< class T >
struct Matrix {
  vector< vector< T > > A;

  Matrix() {}

  Matrix(size_t n, size_t m) : A(n, vector< T >(m, 0)) {}

  Matrix(size_t n) : A(n, vector< T >(n, 0)) {};

  size_t height() const {
    return (A.size());
  }

  size_t width() const {
    return (A[0].size());
  }

  inline const vector< T > &operator[](int k) const {
    return (A.at(k));
  }

  inline vector< T > &operator[](int k) {
    return (A.at(k));
  }

  static Matrix I(size_t n) {
    Matrix mat(n);
    for(int i = 0; i < n; i++) mat[i][i] = 1;
    return (mat);
  }

  Matrix &operator+=(const Matrix &B) {
    size_t n = height(), m = width();
    assert(n == B.height() && m == B.width());
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        (*this)[i][j] += B[i][j];
    return (*this);
  }

  Matrix &operator-=(const Matrix &B) {
    size_t n = height(), m = width();
    assert(n == B.height() && m == B.width());
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        (*this)[i][j] -= B[i][j];
    return (*this);
  }

  Matrix &operator*=(const Matrix &B) {
    if (B.height() == 1 and B.width() == 1){
        auto res = *this * B[0][0];
        this->A = res.A;
        return (*this);
    }

    if (this->height() == 1 and this->width() == 1){
        auto res = (*this)[0][0] * B;
        this->A  = res.A;
        return (*this);
    }

    size_t n = height(), m = B.width(), p = width();
    assert(p == B.height());
    vector< vector< T > > C(n, vector< T >(m, 0));
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        for(int k = 0; k < p; k++)
          C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]);
    A.swap(C);
    return (*this);
  }

  Matrix &operator^=(long long k) {
    Matrix B = Matrix::I(height());
    while(k > 0) {
      if(k & 1) B *= *this;
      *this *= *this;
      k >>= 1LL;
    }
    A.swap(B.A);
    return (*this);
  }

  Matrix operator+(const Matrix &B) const {
    return (Matrix(*this) += B);
  }

  Matrix operator-(const Matrix &B) const {
    return (Matrix(*this) -= B);
  }

  Matrix operator*(const Matrix &B) const {
    if (this->height() == 1 and this->width() == 1)
        return (*this)[0][0] * B;
    return (Matrix(*this) *= B);
  }

  Matrix operator^(const long long k) const {
    return (Matrix(*this) ^= k);
  }

  Matrix operator*(const T &k) const {
      auto res = Matrix(*this);
      for (int i = 0; i < res.height(); i++){
          for (int j = 0; j < res.width(); j++)
            res[i][j] *= k;
      }
      return res;
  }

  friend Matrix operator*(const T &k, const Matrix &p) {
      auto res = Matrix(p);
      for (int i = 0; i < res.height(); i++){
          for (int j = 0; j < res.width(); j++)
            res[i][j] *= k;
      }
      return res;
  }

  friend Matrix concat_v(const Matrix &lhs, const Matrix &rhs){
      assert(lhs.width() == rhs.width());
      Matrix res(lhs.height() + rhs.height(), lhs.width());
      for (int i = 0; i < lhs.height(); i++){
          for (int j = 0; j < lhs.width(); j++)
            res[i][j] = lhs[i][j];
      }
      for (int i = 0; i < rhs.height(); i++){
          for (int j = 0; j < rhs.width(); j++)
            res[lhs.height() + i][j] = rhs[i][j];
      }

      return res;
  }

    friend Matrix concat_w(const Matrix &lhs, const Matrix &rhs){
      assert(lhs.height() == rhs.height());
      Matrix res(lhs.height(), lhs.width() + rhs.width());
      for (int i = 0; i < lhs.height(); i++){
          for (int j = 0; j < lhs.width(); j++)
            res[i][j] = lhs[i][j];
      }
      for (int i = 0; i < rhs.height(); i++){
          for (int j = 0; j < rhs.width(); j++)
            res[i][lhs.width() + j] = rhs[i][j];
      }

      return res;
    }

    Matrix t(){
        Matrix res(this->width(), this->height());
        for (int i = 0; i < this->height(); i++){
            for (int j = 0; j < this->width(); j++)
                res[j][i] = (*this)[i][j];
        }

        return res;
    }

  friend ostream &operator<<(ostream &os, Matrix &p) {
    size_t n = p.height(), m = p.width();
    for(int i = 0; i < n; i++) {
      for(int j = 0; j < m; j++) {
        os << p[i][j] << (j + 1 == m ? "\n" : " ");
      }
    }
    return (os);
  }


  T determinant() {
    Matrix B(*this);
    assert(width() == height());
    T ret = 1;
    for(int i = 0; i < width(); i++) {
      int idx = -1;
      for(int j = i; j < width(); j++) {
        if(B[j][i] != 0) idx = j;
      }
      if(idx == -1) return (0);
      if(i != idx) {
        ret *= -1;
        swap(B[i], B[idx]);
      }
      ret *= B[i][i];
      T vv = B[i][i];
      for(int j = 0; j < width(); j++) {
        B[i][j] /= vv;
      }
      for(int j = i + 1; j < width(); j++) {
        T a = B[j][i];
        for(int k = 0; k < width(); k++) {
          B[j][k] -= B[i][k] * a;
        }
      }
    }
    return (ret);
  }
};

template <std::uint_fast64_t Modulus> class modint {
    using u64 = std::uint_fast64_t;
    u64 a;

    public:

    template <class INT>
    constexpr modint(const INT x = 0) noexcept : a(x >= 0 ? x % Modulus : x % int_fast64_t(Modulus) + Modulus) {}
    constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept {
        return modint(*this) += rhs;
    }
    constexpr modint operator-(const modint rhs) const noexcept {
        return modint(*this) -= rhs;
    }
    constexpr modint operator*(const modint rhs) const noexcept {
        return modint(*this) *= rhs;
    }
    constexpr modint operator/(const modint rhs) const noexcept {
        return modint(*this) /= rhs;
    }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if (a >= Modulus) {
            a -= Modulus;
        }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if (a < rhs.a) {
            a += Modulus;
        }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr modint &operator/=(modint rhs) noexcept {
        u64 exp = Modulus - 2;
        while (exp) {
            if (exp % 2) {
                *this *= rhs;
            }
        rhs *= rhs;
        exp /= 2;
        }
        return *this;
    }

    constexpr bool operator<(const modint& rhs) const noexcept {return this->a < rhs.a;}
    constexpr bool operator>(const modint& rhs) const noexcept {return rhs < *this;}
    constexpr bool operator<=(const modint& rhs) const noexcept {return !(*this > rhs);}
    constexpr bool operator>=(const modint& rhs) const noexcept {return !(*this < rhs);}
    constexpr bool operator==(const modint& rhs) const noexcept {return this->a == rhs.a;}
    constexpr bool operator!=(const modint& rhs) const noexcept {return !(*this == rhs);}

    constexpr modint& operator++() noexcept {
        *this += modint(1);
        return *this;
    }
    constexpr modint operator++(int) noexcept {
        modint tmp(*this);
        ++(*this);
        return tmp;
    }
    constexpr modint& operator--() noexcept {
        *this -= modint(1);
        return *this;
    }
    constexpr modint operator--(int) noexcept {
        modint tmp(*this);
        --(*this);
        return tmp;
    }
    constexpr modint operator-() const noexcept {
        return modint(0) - *this;
    }

    template <std::uint_fast64_t M>
    friend constexpr std::ostream& operator<<(std::ostream& os, const modint<M>& rhs) noexcept {
        os << rhs.a;
        return os;
    }
    template <std::uint_fast64_t M>
    friend constexpr std::istream& operator>>(std::istream& is, modint<M>& rhs) noexcept {
        int64_t tmp;
        is >> tmp;
        rhs = modint(tmp);
        return is;
    }

    constexpr modint pow(const u64 k) const noexcept {
        if (k == 0)
            return 1;
        if (k % 2 == 0){
            modint res = pow(k / 2);
            return res * res;
        }
        return pow(k - 1) * modint(*this);
    }

    template <typename T>
    operator const T (){return a;}

};

using mint = modint<32768>;

class Parser{
    string S;
    int pos = 0;
    map<char, Matrix<mint>> vars;
    public:
    Parser(string T) : S(T){}

    void set_s(string s){
        S = s;
        pos = 0;
    }

    char peek(){
        // if (pos < S.size())
        //     cerr << S[pos] << endl;
        return pos < S.size() ? S[pos] : 'a';
    }

    bool is_number(char c){
        return '0' <= c and c <= '9';
    }

    bool is_A_to_Z(char c){
        return 'A' <= c and c <= 'Z';
    }

    void skip_spaces(){
        while (peek() == ' ')
            pos++;
    }

    void next(bool state){
        assert(state);
        pos++;
    }

    Matrix<mint> assignment(){
        char var_c = var();
        next(peek() == '=');
        vars[var_c] = expr();
        next(peek() == '.');
        
        return vars[var_c];
    }

    char var(){
        char res = peek();
        next('A' <= peek() and peek() <= 'Z');
        return res;
    }

    Matrix<mint> expr(){
        Matrix<mint> res = term();
        while (peek() == '+' or peek() == '-'){
            if (peek() == '+'){
                pos++;
                res += term();
            } else if (peek() == '-'){
                pos++;
                res -= term();
            }
        }
        return res;
    }

    Matrix<mint> term(){
        Matrix<mint> res = factor();
        while (peek() == '*'){
            pos++;
            res *= factor();
        }

        return res;
    }

    Matrix<mint> factor(){
        if (peek() == '-'){
            pos++;
            return mint(-1) * factor();
        }

        return primary();
    }

    Matrix<mint> primary(){
        auto res = Matrix<mint>(1, 1);
        res[0][0] = -1;
        if (is_number(peek())){
            res[0][0] = number();
        } else if (is_A_to_Z(peek())){
            auto v = var();
            res = vars[v];
        } else if (peek() == '['){
            res = matrix();
        } else if (peek() == '('){
            pos++;
            res = expr();
            next(peek() == ')');
        }

        while (is_index() or peek() == '\''){
            if (peek() == '\''){
                pos++;
                res = res.t();
            } else if (is_index()){
                next(peek() == '(');
                auto left = expr();
                next(peek() == ',');
                auto right = expr();
                next(peek() == ')');
                Matrix<mint> res2(left.width(), right.width());
                for (int i = 0; i < left.width(); i++){
                    for (int j = 0; j < right.width(); j++)
                        res2[i][j] = res[left[0][i] - 1][right[0][j] - 1];
                }
                res = res2;
            }
        }

        return res;
    }

    bool is_index(){
        if (peek() != '(')
            return false;
        int c = 0;
        for (int i = pos; i < S.size(); i++){
            if (S[i] == '(')
                c++;
            if (S[i] == ')'){
                c--;
                if (c == 0)
                    break;
            }
            if (S[i] == ',' and c == 1)
                return true;
        }
        return false;
    }

    Matrix<mint> matrix(){
        next(peek() == '[');
        auto res = row_seq();
        next(peek() == ']');
        return res;
    }

    Matrix<mint> row_seq(){
        auto res = row();
        while (peek() == ';'){
            pos++;
            res = concat_v(res, row());
        }
        return res;
    }

    Matrix<mint> row(){
        auto res = expr();
        while (peek() == ' '){
            pos++;
            res = concat_w(res, expr());
        }
        return res;
    }

    mint number(){
        mint res = 0;
        while (is_number(peek())){
            res = res * 10 + peek() - '0';
            pos++;
        }
        return res;
    }
};

void solve(int n){
    string stash;
    getline(cin, stash);
    Parser parser("");
    for (int i = 0; i < n; i++){
        string s;
        getline(cin, s);
        parser.set_s(s);
        auto res = parser.assignment();
        cout << res;
    }
    puts("-----");
}

int main(){
    int n;
    while (true){
        cin >> n;
        if (n == 0)
            break;
        solve(n);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3952
final_rank: 15

code_snippet: #include <bits/stdc++.h>

using namespace std;

template< class T >
struct Matrix {
  vector< vector< T > > A;

  Matrix() {}

  Matrix(size_t n, size_t m) : A(n, vector< T >(m, 0)) {}

  Matrix(size_t n) : A(n, vector< T >(n, 0)) {};

  size_t height() const {
    return (A.size());
  }

  size_t width() const {
    return (A[0].size());
  }

  inline const vector< T > &operator[](int k) const {
    return (A.at(k));
  }

  inline vector< T > &operator[](int k) {
    return (A.at(k));
  }

  static Matrix I(size_t n) {
    Matrix mat(n);
    for(int i = 0; i < n; i++) mat[i][i] = 1;
    return (mat);
  }

  Matrix &operator+=(const Matrix &B) {
    size_t n = height(), m = width();
    assert(n == B.height() && m == B.width());
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        (*this)[i][j] += B[i][j];
    return (*this);
  }

  Matrix &operator-=(const Matrix &B) {
    size_t n = height(), m = width();
    assert(n == B.height() && m == B.width());
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        (*this)[i][j] -= B[i][j];
    return (*this);
  }

  Matrix &operator*=(const Matrix &B) {
    if (B.height() == 1 and B.width() == 1){
        auto res = *this * B[0][0];
        this->A = res.A;
        return (*this);
    }

    if (this->height() == 1 and this->width() == 1){
        auto res = (*this)[0][0] * B;
        this->A  = res.A;
        return (*this);
    }

    size_t n = height(), m = B.width(), p = width();
    assert(p == B.height());
    vector< vector< T > > C(n, vector< T >(m, 0));
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        for(int k = 0; k < p; k++)
          C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]);
    A.swap(C);
    return (*this);
  }

  Matrix &operator^=(long long k) {
    Matrix B = Matrix::I(height());
    while(k > 0) {
      if(k & 1) B *= *this;
      *this *= *this;
      k >>= 1LL;
    }
    A.swap(B.A);
    return (*this);
  }

  Matrix operator+(const Matrix &B) const {
    return (Matrix(*this) += B);
  }

  Matrix operator-(const Matrix &B) const {
    return (Matrix(*this) -= B);
  }

  Matrix operator*(const Matrix &B) const {
    if (this->height() == 1 and this->width() == 1)
        return (*this)[0][0] * B;
    return (Matrix(*this) *= B);
  }

  Matrix operator^(const long long k) const {
    return (Matrix(*this) ^= k);
  }

  Matrix operator*(const T &k) const {
      auto res = Matrix(*this);
      for (int i = 0; i < res.height(); i++){
          for (int j = 0; j < res.width(); j++)
            res[i][j] *= k;
      }
      return res;
  }

  friend Matrix operator*(const T &k, const Matrix &p) {
      auto res = Matrix(p);
      for (int i = 0; i < res.height(); i++){
          for (int j = 0; j < res.width(); j++)
            res[i][j] *= k;
      }
      return res;
  }

  friend Matrix concat_v(const Matrix &lhs, const Matrix &rhs){
      assert(lhs.width() == rhs.width());
      Matrix res(lhs.height() + rhs.height(), lhs.width());
      for (int i = 0; i < lhs.height(); i++){
          for (int j = 0; j < lhs.width(); j++)
            res[i][j] = lhs[i][j];
      }
      for (int i = 0; i < rhs.height(); i++){
          for (int j = 0; j < rhs.width(); j++)
            res[lhs.height() + i][j] = rhs[i][j];
      }

      return res;
  }

    friend Matrix concat_w(const Matrix &lhs, const Matrix &rhs){
      assert(lhs.height() == rhs.height());
      Matrix res(lhs.height(), lhs.width() + rhs.width());
      for (int i = 0; i < lhs.height(); i++){
          for (int j = 0; j < lhs.width(); j++)
            res[i][j] = lhs[i][j];
      }
      for (int i = 0; i < rhs.height(); i++){
          for (int j = 0; j < rhs.width(); j++)
            res[i][lhs.width() + j] = rhs[i][j];
      }

      return res;
    }

    Matrix t(){
        Matrix res(this->width(), this->height());
        for (int i = 0; i < this->height(); i++){
            for (int j = 0; j < this->width(); j++)
                res[j][i] = (*this)[i][j];
        }

        return res;
    }

  friend ostream &operator<<(ostream &os, Matrix &p) {
    size_t n = p.height(), m = p.width();
    for(int i = 0; i < n; i++) {
      for(int j = 0; j < m; j++) {
        os << p[i][j] << (j + 1 == m ? "\n" : " ");
      }
    }
    return (os);
  }


  T determinant() {
    Matrix B(*this);
    assert(width() == height());
    T ret = 1;
    for(int i = 0; i < width(); i++) {
      int idx = -1;
      for(int j = i; j < width(); j++) {
        if(B[j][i] != 0) idx = j;
      }
      if(idx == -1) return (0);
      if(i != idx) {
        ret *= -1;
        swap(B[i], B[idx]);
      }
      ret *= B[i][i];
      T vv = B[i][i];
      for(int j = 0; j < width(); j++) {
        B[i][j] /= vv;
      }
      for(int j = i + 1; j < width(); j++) {
        T a = B[j][i];
        for(int k = 0; k < width(); k++) {
          B[j][k] -= B[i][k] * a;
        }
      }
    }
    return (ret);
  }
};

template <std::uint_fast64_t Modulus> class modint {
    using u64 = std::uint_fast64_t;
    u64 a;

    public:

    template <class INT>
    constexpr modint(const INT x = 0) noexcept : a(x >= 0 ? x % Modulus : x % int_fast64_t(Modulus) + Modulus) {}
    constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept {
        return modint(*this) += rhs;
    }
    constexpr modint operator-(const modint rhs) const noexcept {
        return modint(*this) -= rhs;
    }
    constexpr modint operator*(const modint rhs) const noexcept {
        return modint(*this) *= rhs;
    }
    constexpr modint operator/(const modint rhs) const noexcept {
        return modint(*this) /= rhs;
    }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if (a >= Modulus) {
            a -= Modulus;
        }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if (a < rhs.a) {
            a += Modulus;
        }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr modint &operator/=(modint rhs) noexcept {
        u64 exp = Modulus - 2;
        while (exp) {
            if (exp % 2) {
                *this *= rhs;
            }
        rhs *= rhs;
        exp /= 2;
        }
        return *this;
    }

    constexpr bool operator<(const modint& rhs) const noexcept {return this->a < rhs.a;}
    constexpr bool operator>(const modint& rhs) const noexcept {return rhs < *this;}
    constexpr bool operator<=(const modint& rhs) const noexcept {return !(*this > rhs);}
    constexpr bool operator>=(const modint& rhs) const noexcept {return !(*this < rhs);}
    constexpr bool operator==(const modint& rhs) const noexcept {return this->a == rhs.a;}
    constexpr bool operator!=(const modint& rhs) const noexcept {return !(*this == rhs);}

    constexpr modint& operator++() noexcept {
        *this += modint(1);
        return *this;
    }
    constexpr modint operator++(int) noexcept {
        modint tmp(*this);
        ++(*this);
        return tmp;
    }
    constexpr modint& operator--() noexcept {
        *this -= modint(1);
        return *this;
    }
    constexpr modint operator--(int) noexcept {
        modint tmp(*this);
        --(*this);
        return tmp;
    }
    constexpr modint operator-() const noexcept {
        return modint(0) - *this;
    }

    template <std::uint_fast64_t M>
    friend constexpr std::ostream& operator<<(std::ostream& os, const modint<M>& rhs) noexcept {
        os << rhs.a;
        return os;
    }
    template <std::uint_fast64_t M>
    friend constexpr std::istream& operator>>(std::istream& is, modint<M>& rhs) noexcept {
        int64_t tmp;
        is >> tmp;
        rhs = modint(tmp);
        return is;
    }

    constexpr modint pow(const u64 k) const noexcept {
        if (k == 0)
            return 1;
        if (k % 2 == 0){
            modint res = pow(k / 2);
            return res * res;
        }
        return pow(k - 1) * modint(*this);
    }

    template <typename T>
    operator const T (){return a;}

};

using mint = modint<32768>;

class Parser{
    string S;
    int pos = 0;
    map<char, Matrix<mint>> vars;
    public:
    Parser(string T) : S(T){}

    void set_s(string s){
        S = s;
        pos = 0;
    }

    char peek(){
        // if (pos < S.size())
        //     cerr << S[pos] << endl;
        return pos < S.size() ? S[pos] : 'a';
    }

    bool is_number(char c){
        return '0' <= c and c <= '9';
    }

    bool is_A_to_Z(char c){
        return 'A' <= c and c <= 'Z';
    }

    void skip_spaces(){
        while (peek() == ' ')
            pos++;
    }

    Matrix<mint> assignment(){
        char var_c = var();
        assert(peek() == '=');
        pos++;
        vars[var_c] = expr();
        assert(peek() == '.');
        pos++;

        return vars[var_c];
    }

    char var(){
        assert('A' <= peek() and peek() <= 'Z');
        char res = peek();
        pos++;
        return res;
    }

    Matrix<mint> expr(){
        Matrix<mint> res = term();
        while (peek() == '+' or peek() == '-'){
            if (peek() == '+'){
                pos++;
                res += term();
            } else if (peek() == '-'){
                pos++;
                res -= term();
            }
        }
        return res;
    }

    Matrix<mint> term(){
        Matrix<mint> res = factor();
        while (peek() == '*'){
            pos++;
            res *= factor();
        }

        return res;
    }

    Matrix<mint> factor(){
        if (peek() == '-'){
            pos++;
            return mint(-1) * factor();
        }

        return primary();
    }

    Matrix<mint> primary(){
        auto res = Matrix<mint>(1, 1);
        res[0][0] = -1;
        if (is_number(peek())){
            res[0][0] = number();
        } else if (is_A_to_Z(peek())){
            auto v = var();
            res = vars[v];
        } else if (peek() == '['){
            res = matrix();
        } else if (peek() == '('){
            pos++;
            res = expr();
            assert(peek() == ')');
            pos++;
        }

        while (is_index() or peek() == '\''){
            if (peek() == '\''){
                pos++;
                res = res.t();
            } else if (is_index()){
                assert(peek() == '(');
                pos++;
                auto left = expr();
                assert(peek() == ',');
                pos++;
                auto right = expr();
                assert(peek() == ')');
                pos++;
                Matrix<mint> res2(left.width(), right.width());
                for (int i = 0; i < left.width(); i++){
                    for (int j = 0; j < right.width(); j++)
                        res2[i][j] = res[left[0][i] - 1][right[0][j] - 1];
                }
                res = res2;
            }
        }

        return res;
    }

    bool is_index(){
        if (peek() != '(')
            return false;
        int c = 0;
        for (int i = pos; i < S.size(); i++){
            if (S[i] == '(')
                c++;
            if (S[i] == ')'){
                c--;
                if (c == 0)
                    break;
            }
            if (S[i] == ',' and c == 1)
                return true;
        }
        return false;
    }

    Matrix<mint> matrix(){
        assert(peek() == '[');
        pos++;
        auto res = row_seq();
        assert(peek() == ']');
        pos++;
        return res;
    }

    Matrix<mint> row_seq(){
        auto res = row();
        while (peek() == ';'){
            pos++;
            res = concat_v(res, row());
        }
        return res;
    }

    Matrix<mint> row(){
        auto res = expr();
        while (peek() == ' '){
            pos++;
            res = concat_w(res, expr());
        }
        return res;
    }

    mint number(){
        mint res = 0;
        while (is_number(peek())){
            res = res * 10 + peek() - '0';
            pos++;
        }
        return res;
    }
};

void solve(int n){
    string stash;
    getline(cin, stash);
    Parser parser("");
    for (int i = 0; i < n; i++){
        string s;
        getline(cin, s);
        parser.set_s(s);
        auto res = parser.assignment();
        cout << res;
    }
    puts("-----");
}

int main(){
    int n;
    while (true){
        cin >> n;
        if (n == 0)
            break;
        solve(n);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3784
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

template< class T >
struct Matrix {
  vector< vector< T > > A;

  Matrix() {}

  Matrix(size_t n, size_t m) : A(n, vector< T >(m, 0)) {}

  Matrix(size_t n) : A(n, vector< T >(n, 0)) {};

  size_t height() const {
    return (A.size());
  }

  size_t width() const {
    return (A[0].size());
  }

  inline const vector< T > &operator[](int k) const {
    return (A.at(k));
  }

  inline vector< T > &operator[](int k) {
    return (A.at(k));
  }

  static Matrix I(size_t n) {
    Matrix mat(n);
    for(int i = 0; i < n; i++) mat[i][i] = 1;
    return (mat);
  }

  Matrix &operator+=(const Matrix &B) {
    size_t n = height(), m = width();
    assert(n == B.height() && m == B.width());
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        (*this)[i][j] += B[i][j];
    return (*this);
  }

  Matrix &operator-=(const Matrix &B) {
    size_t n = height(), m = width();
    assert(n == B.height() && m == B.width());
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        (*this)[i][j] -= B[i][j];
    return (*this);
  }

  Matrix &operator*=(const Matrix &B) {
    if (B.height() == 1 and B.width() == 1){
        auto res = *this * B[0][0];
        this->A = res.A;
        return (*this);
    }

    if (this->height() == 1 and this->width() == 1){
        auto res = (*this)[0][0] * B;
        this->A  = res.A;
        return (*this);
    }

    size_t n = height(), m = B.width(), p = width();
    assert(p == B.height());
    vector< vector< T > > C(n, vector< T >(m, 0));
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        for(int k = 0; k < p; k++)
          C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]);
    A.swap(C);
    return (*this);
  }

  Matrix &operator^=(long long k) {
    Matrix B = Matrix::I(height());
    while(k > 0) {
      if(k & 1) B *= *this;
      *this *= *this;
      k >>= 1LL;
    }
    A.swap(B.A);
    return (*this);
  }

  Matrix operator+(const Matrix &B) const {
    return (Matrix(*this) += B);
  }

  Matrix operator-(const Matrix &B) const {
    return (Matrix(*this) -= B);
  }

  Matrix operator*(const Matrix &B) const {
    if (this->height() == 1 and this->width() == 1)
        return (*this)[0][0] * B;
    return (Matrix(*this) *= B);
  }

  Matrix operator^(const long long k) const {
    return (Matrix(*this) ^= k);
  }

  Matrix operator*(const T &k) const {
      auto res = Matrix(*this);
      for (int i = 0; i < res.height(); i++){
          for (int j = 0; j < res.width(); j++)
            res[i][j] *= k;
      }
      return res;
  }

  friend Matrix operator*(const T &k, const Matrix &p) {
      auto res = Matrix(p);
      for (int i = 0; i < res.height(); i++){
          for (int j = 0; j < res.width(); j++)
            res[i][j] *= k;
      }
      return res;
  }

  friend Matrix concat_v(const Matrix &lhs, const Matrix &rhs){
      assert(lhs.width() == rhs.width());
      Matrix res(lhs.height() + rhs.height(), lhs.width());
      for (int i = 0; i < lhs.height(); i++){
          for (int j = 0; j < lhs.width(); j++)
            res[i][j] = lhs[i][j];
      }
      for (int i = 0; i < rhs.height(); i++){
          for (int j = 0; j < rhs.width(); j++)
            res[lhs.height() + i][j] = rhs[i][j];
      }

      return res;
  }

    friend Matrix concat_w(const Matrix &lhs, const Matrix &rhs){
      assert(lhs.height() == rhs.height());
      Matrix res(lhs.height(), lhs.width() + rhs.width());
      for (int i = 0; i < lhs.height(); i++){
          for (int j = 0; j < lhs.width(); j++)
            res[i][j] = lhs[i][j];
      }
      for (int i = 0; i < rhs.height(); i++){
          for (int j = 0; j < rhs.width(); j++)
            res[i][lhs.width() + j] = rhs[i][j];
      }

      return res;
    }

    Matrix t(){
        Matrix res(this->width(), this->height());
        for (int i = 0; i < this->height(); i++){
            for (int j = 0; j < this->width(); j++)
                res[j][i] = (*this)[i][j];
        }

        return res;
    }

  friend ostream &operator<<(ostream &os, Matrix &p) {
    size_t n = p.height(), m = p.width();
    for(int i = 0; i < n; i++) {
      for(int j = 0; j < m; j++) {
        os << p[i][j] << (j + 1 == m ? "\n" : " ");
      }
    }
    return (os);
  }


  T determinant() {
    Matrix B(*this);
    assert(width() == height());
    T ret = 1;
    for(int i = 0; i < width(); i++) {
      int idx = -1;
      for(int j = i; j < width(); j++) {
        if(B[j][i] != 0) idx = j;
      }
      if(idx == -1) return (0);
      if(i != idx) {
        ret *= -1;
        swap(B[i], B[idx]);
      }
      ret *= B[i][i];
      T vv = B[i][i];
      for(int j = 0; j < width(); j++) {
        B[i][j] /= vv;
      }
      for(int j = i + 1; j < width(); j++) {
        T a = B[j][i];
        for(int k = 0; k < width(); k++) {
          B[j][k] -= B[i][k] * a;
        }
      }
    }
    return (ret);
  }
};

template <std::uint_fast64_t Modulus> class modint {
    using u64 = std::uint_fast64_t;
    u64 a;

    public:

    template <class INT>
    constexpr modint(const INT x = 0) noexcept : a(x >= 0 ? x % Modulus : x % int_fast64_t(Modulus) + Modulus) {}
    constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept {
        return modint(*this) += rhs;
    }
    constexpr modint operator-(const modint rhs) const noexcept {
        return modint(*this) -= rhs;
    }
    constexpr modint operator*(const modint rhs) const noexcept {
        return modint(*this) *= rhs;
    }
    constexpr modint operator/(const modint rhs) const noexcept {
        return modint(*this) /= rhs;
    }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if (a >= Modulus) {
            a -= Modulus;
        }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if (a < rhs.a) {
            a += Modulus;
        }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr modint &operator/=(modint rhs) noexcept {
        u64 exp = Modulus - 2;
        while (exp) {
            if (exp % 2) {
                *this *= rhs;
            }
        rhs *= rhs;
        exp /= 2;
        }
        return *this;
    }

    constexpr bool operator<(const modint& rhs) const noexcept {return this->a < rhs.a;}
    constexpr bool operator>(const modint& rhs) const noexcept {return rhs < *this;}
    constexpr bool operator<=(const modint& rhs) const noexcept {return !(*this > rhs);}
    constexpr bool operator>=(const modint& rhs) const noexcept {return !(*this < rhs);}
    constexpr bool operator==(const modint& rhs) const noexcept {return this->a == rhs.a;}
    constexpr bool operator!=(const modint& rhs) const noexcept {return !(*this == rhs);}

    constexpr modint& operator++() noexcept {
        *this += modint(1);
        return *this;
    }
    constexpr modint operator++(int) noexcept {
        modint tmp(*this);
        ++(*this);
        return tmp;
    }
    constexpr modint& operator--() noexcept {
        *this -= modint(1);
        return *this;
    }
    constexpr modint operator--(int) noexcept {
        modint tmp(*this);
        --(*this);
        return tmp;
    }
    constexpr modint operator-() const noexcept {
        return modint(0) - *this;
    }

    template <std::uint_fast64_t M>
    friend constexpr std::ostream& operator<<(std::ostream& os, const modint<M>& rhs) noexcept {
        os << rhs.a;
        return os;
    }
    template <std::uint_fast64_t M>
    friend constexpr std::istream& operator>>(std::istream& is, modint<M>& rhs) noexcept {
        int64_t tmp;
        is >> tmp;
        rhs = modint(tmp);
        return is;
    }

    constexpr modint pow(const u64 k) const noexcept {
        if (k == 0)
            return 1;
        if (k % 2 == 0){
            modint res = pow(k / 2);
            return res * res;
        }
        return pow(k - 1) * modint(*this);
    }

    template <typename T>
    operator const T (){return a;}

};

using mint = modint<32768>;

class Parser{
    string S;
    int pos = 0;
    map<char, Matrix<mint>> vars;
    public:
    Parser(string T) : S(T){}

    void set_s(string s){
        S = s;
        pos = 0;
    }

    char peek(){
        // if (pos < S.size())
        //     cerr << S[pos] << endl;
        return pos < S.size() ? S[pos] : 'a';
    }

    bool is_number(char c){
        return '0' <= c and c <= '9';
    }

    bool is_A_to_Z(char c){
        return 'A' <= c and c <= 'Z';
    }

    void skip_spaces(){
        while (peek() == ' ')
            pos++;
    }

    Matrix<mint> assignment(){
        char var_c = var();
        assert(peek() == '=');
        pos++;
        vars[var_c] = expr();
        assert(peek() == '.');
        pos++;

        return vars[var_c];
    }

    char var(){
        assert('A' <= peek() and peek() <= 'Z');
        char res = peek();
        pos++;
        return res;
    }

    Matrix<mint> expr(){
        Matrix<mint> res = term();
        while (peek() == '+' or peek() == '-'){
            if (peek() == '+'){
                pos++;
                res += term();
            } else if (peek() == '-'){
                pos++;
                res -= term();
            }
        }
        return res;
    }

    Matrix<mint> term(){
        Matrix<mint> res = factor();
        while (peek() == '*'){
            pos++;
            res *= factor();
        }

        return res;
    }

    Matrix<mint> factor(){
        if (peek() == '-'){
            pos++;
            return mint(-1) * factor();
        }

        return primary();
    }

    Matrix<mint> primary(){
        auto res = Matrix<mint>(1, 1);
        res[0][0] = -1;
        if (is_number(peek())){
            res[0][0] = number();
        } else if (is_A_to_Z(peek())){
            auto v = var();
            res = vars[v];
        } else if (peek() == '['){
            res = matrix();
        }

        if (!is_index() and peek() == '('){
            pos++;
            res = expr();
            assert(peek() == ')');
            pos++;
        }

        while (is_index() or peek() == '\''){
            if (peek() == '\''){
                pos++;
                res = res.t();
            } else if (is_index()){
                assert(peek() == '(');
                pos++;
                auto left = expr();
                assert(peek() == ',');
                pos++;
                auto right = expr();
                assert(peek() == ')');
                pos++;
                Matrix<mint> res2(left.width(), right.width());
                for (int i = 0; i < left.width(); i++){
                    for (int j = 0; j < right.width(); j++)
                        res2[i][j] = res[left[0][i] - 1][right[0][j] - 1];
                }
                res = res2;
            }
        }

        return res;
    }

    bool is_index(){
        if (peek() != '(')
            return false;
        int c = 0;
        for (int i = pos; i < S.size(); i++){
            if (S[i] == '(')
                c++;
            if (S[i] == ')'){
                c--;
                if (c == 0)
                    break;
            }
            if (S[i] == ',' and c == 1)
                return true;
        }
        return false;
    }

    Matrix<mint> matrix(){
        assert(peek() == '[');
        pos++;
        auto res = row_seq();
        assert(peek() == ']');
        pos++;
        return res;
    }

    Matrix<mint> row_seq(){
        auto res = row();
        while (peek() == ';'){
            pos++;
            res = concat_v(res, row());
        }
        return res;
    }

    Matrix<mint> row(){
        auto res = expr();
        while (peek() == ' '){
            pos++;
            res = concat_w(res, expr());
        }
        return res;
    }

    mint number(){
        mint res = 0;
        while (is_number(peek())){
            res = res * 10 + peek() - '0';
            pos++;
        }
        return res;
    }
};

void solve(int n){
    string stash;
    getline(cin, stash);
    Parser parser("");
    for (int i = 0; i < n; i++){
        string s;
        getline(cin, s);
        parser.set_s(s);
        auto res = parser.assignment();
        cout << res;
    }
    puts("-----");
}

int main(){
    int n;
    while (true){
        cin >> n;
        if (n == 0)
            break;
        solve(n);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3708
final_rank: 9

code_snippet: /*	author:  Kite_kuma
	created: 2021.10.10 10:33:56 */

#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region modint

const int mod = (1 << 15);

template <int mod>
struct ModInt {
	int x;
	ModInt() : x(0) {}
	ModInt(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
	ModInt &operator+=(const ModInt &p) {
		if((x += p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator-=(const ModInt &p) {
		if((x += mod - p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator*=(const ModInt &p) {
		x = (int)(1LL * x * p.x % mod);
		return *this;
	}
	ModInt &operator/=(const ModInt &p) {
		*this *= p.inverse();
		return *this;
	}
	ModInt operator-() const { return ModInt(-x); }
	ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
	ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
	ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
	ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
	bool operator==(const ModInt &p) const { return x == p.x; }
	bool operator!=(const ModInt &p) const { return x != p.x; }
	ModInt inverse() const {
		int a = x, b = mod, u = 1, v = 0, t;
		while(b > 0) {
			t = a / b;
			swap(a -= t * b, b);
			swap(u -= t * v, v);
		}
		return ModInt(u);
	}
	ModInt pow(long long n) const {
		ModInt ret(1), mul(x);
		while(n > 0) {
			if(n & 1) ret *= mul;
			mul *= mul;
			n >>= 1;
		}
		return ret;
	}
	friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }
	friend istream &operator>>(istream &is, ModInt &a) {
		long long t;
		is >> t;
		a = ModInt<mod>(t);
		return (is);
	}
	static int get_mod() { return mod; }
};
using mint = ModInt<mod>;

#pragma endregion

struct matrix {
	int row_size, col_size;
	VV<mint> mat;

	matrix() = default;
	matrix(int h, int w, mint value = 0) : row_size(h), col_size(w), mat(h, V<mint>(w, value)) {}
	matrix(mint val) : row_size(1), col_size(1), mat(1, V<mint>(1, val)) {}
	matrix(VV<mint> m) : row_size(m.size()), col_size(m[0].size()), mat(m) {}

	V<mint> &operator[](int idx) { return mat[idx]; }

	matrix operator+(matrix right) {
		assert(row_size == right.row_size && col_size == right.col_size);
		auto ret = mat;
		rep(i, row_size) rep(j, col_size) { ret[i][j] += right[i][j]; }
		return ret;
	}

	matrix operator-(matrix right) {
		assert(row_size == right.row_size && col_size == right.col_size);
		auto ret = mat;
		rep(i, row_size) rep(j, col_size) { ret[i][j] -= right[i][j]; }
		return ret;
	}

	matrix operator*(mint right) {
		auto ret = mat;
		rep(i, row_size) rep(j, col_size) { ret[i][j] *= right; }
		return ret;
	}

	matrix operator*(matrix right) {
		if(right.row_size + right.col_size == 2) return *(this) * right[0][0];
		if(row_size + col_size == 2) return right * mat[0][0];
		assert(col_size == right.row_size);
		matrix ret(row_size, right.col_size);
		rep(i, row_size) rep(k, col_size) rep(j, right.col_size) { ret[i][j] += mat[i][k] * right[k][j]; }
		return ret;
	}

	matrix conjugate_side(matrix right) {
		assert(row_size == right.row_size);
		VV<mint> ret = mat;
		rep(r, row_size) {
			rep(c, right.col_size) { ret[r].push_back(right[r][c]); }
		}
		return matrix(ret);
	}

	matrix conjugate_bottom(matrix under) {
		if(col_size != under.col_size) {
			debug(mat);
			debug(under.mat);
			debug(col_size, under.col_size);
			assert(false);
		}
		VV<mint> ret = mat;
		foa(v, under.mat) { ret.push_back(v); }
		return ret;
	}

	matrix transpose() {
		matrix ret(col_size, row_size);
		rep(i, row_size) rep(j, col_size) ret[j][i] = mat[i][j];
		return ret;
	}

	void print() {
		rep(i, row_size) {
			rep(j, col_size) {
				cout << mat[i][j];
				if(j == col_size - 1) {
					cout << dl;
				} else
					cout << sp;
			}
		}
	}
};

string s;
string::iterator it;
V<matrix> vars(26);
struct parser {
	parser() { it = s.begin(); }
	void consume(const char &c) {
		if(*it == c) {
			it++;
			return;
		}
		debug(s);
		debug(it - s.begin());
		debug("consumed:", c);
		if(it != s.end())
			cerr << "but in this case" << '\'' << *it << '\'';
		else
			cerr << "but in this case, program has ended";
		cerr << dl;
		exit(0);
	}
	matrix assignment() {
		int v = var();
		consume('=');
		debug("eq", v, it - s.begin());
		matrix e = expr();
		debug(e.mat);
		consume('.');
		assert(it == s.end());
		vars[v] = e;
		return e;
	}
	mint dig() { return *it++ - '0'; }
	mint inum() {
		mint ret = 0;
		assert(isdigit(*it));
		while(isdigit(*it)) {
			ret *= 10;
			ret += dig();
		}
		return ret;
	}

	int var() {
		assert(isalpha(*it));
		return *it++ - 'A';
	}
	matrix expr() {
		matrix ret = term();
		while(it != s.end()) {
			if(*it == '+') {
				consume('+');
				ret = ret + term();
			} else if(*it == '-') {
				consume('-');
				ret = ret - term();
			} else {
				break;
			}
		}
		debug(ret.mat, it - s.begin());
		return ret;
	}
	matrix term() {
		matrix ret = factor();
		while(it != s.end() && *it == '*') {
			consume('*');
			ret = ret * factor();
		}
		debug(ret.mat, it - s.begin());
		return ret;
	}
	matrix factor() {
		if(*it == '-') {
			consume('-');
			return factor() * mint(-1);
		}
		return primary();
	}
	matrix primary() {
		matrix ret;
		if(isalpha(*it))
			ret = matrix(vars[var()]);
		else if(isdigit(*it))
			ret = inum();
		else if(*it == '(') {
			consume('(');
			ret = expr();
			consume(')');
		} else {
			consume('[');
			ret = row_seq();
			consume(']');
		}
		while(it != s.end()) {
			if(*it == '\'') {
				consume('\'');
				ret = ret.transpose();
			} else if(*it == '(') {
				consume('(');
				matrix rows = expr();
				consume(',');
				matrix cols = expr();
				consume(')');
				assert(rows.row_size == 1);
				assert(cols.row_size == 1);
				matrix nxt(rows.col_size, cols.col_size);
				rep(i, rows.col_size) rep(j, cols.col_size) { nxt[i][j] = ret[(rows[0][i] - 1).x][(cols[0][j] - 1).x]; }
				swap(nxt, ret);
			} else {
				break;
			}
		}
		return ret;
	}
	// mat indexed_primary() {}
	// mat transposed_primary() {}
	matrix row_seq() {
		matrix ret = row();
		debug(ret.mat);
		while(it != s.end() && *it == ';') {
			consume(';');
			ret = ret.conjugate_bottom(row());
			debug(ret.mat);
		}
		debug(ret.mat);
		return ret;
	}
	matrix row() {
		matrix ret = expr();
		while(it != s.end() && *it == ' ') {
			consume(' ');
			ret = ret.conjugate_side(expr());
		}
		debug(ret.mat);
		return ret;
	}
};

void solve(int n) {
	cin.ignore();
	rep(n) {
		debug(n);
		getline(cin, s);
		debug(s);
		parser ps;
		ps.assignment().print();
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) {
		solve(n);
		cout << "-----" << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3764
final_rank: 12

code_snippet: #define MOD_TYPE 1

#include <bits/stdc++.h>
using namespace std;

//#include <atcoder/all>


#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m < 2^31`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using namespace atcoder;

#if 0
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
using Int = boost::multiprecision::cpp_int;
using lld = boost::multiprecision::cpp_dec_float_100;
#endif

#if 1
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#endif

#pragma region Macros

using ll = long long int;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pld = pair<ld, ld>;
template <typename Q_type>
using smaller_queue = priority_queue<Q_type, vector<Q_type>, greater<Q_type>>;

#if MOD_TYPE == 1
constexpr ll MOD = ll(1e9 + 7);
#else
#if MOD_TYPE == 2
constexpr ll MOD = 998244353;
#else
constexpr ll MOD = 1000003;
#endif
#endif

using mint = static_modint<MOD>;
constexpr int INF = (int)1e9 + 10;
constexpr ll LINF = (ll)4e18;
constexpr double PI = acos(-1.0);
constexpr double EPS = 1e-11;
constexpr int Dx[] = {0, 0, -1, 1, -1, 1, -1, 1, 0};
constexpr int Dy[] = {1, -1, 0, 0, -1, -1, 1, 1, 0};

#define REP(i, m, n) for (ll i = m; i < (ll)(n); ++i)
#define rep(i, n) REP(i, 0, n)
#define REPI(i, m, n) for (int i = m; i < (int)(n); ++i)
#define repi(i, n) REPI(i, 0, n)
#define MP make_pair
#define MT make_tuple
#define YES(n) cout << ((n) ? "YES" : "NO") << "\n"
#define Yes(n) cout << ((n) ? "Yes" : "No") << "\n"
#define possible(n) cout << ((n) ? "possible" : "impossible") << "\n"
#define Possible(n) cout << ((n) ? "Possible" : "Impossible") << "\n"
#define Yay(n) cout << ((n) ? "Yay!" : ":(") << "\n"
#define all(v) v.begin(), v.end()
#define NP(v) next_permutation(all(v))
#define dbg(x) cerr << #x << ":" << x << "\n";
#define UNIQUE(v) v.erase(unique(all(v)), v.end())

struct io_init {
  io_init() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << setprecision(30) << setiosflags(ios::fixed);
  };
} io_init;
template <typename T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
inline ll CEIL(ll a, ll b) { return (a + b - 1) / b; }
template <typename A, size_t N, typename T>
inline void Fill(A (&array)[N], const T& val) {
  fill((T*)array, (T*)(array + N), val);
}
template <typename T>
vector<T> compress(vector<T>& v) {
  vector<T> val = v;
  sort(all(val)), val.erase(unique(all(val)), val.end());
  for (auto&& vi : v) vi = lower_bound(all(val), vi) - val.begin();
  return val;
}
template <typename T, typename U>
constexpr istream& operator>>(istream& is, pair<T, U>& p) noexcept {
  is >> p.first >> p.second;
  return is;
}
template <typename T, typename U>
constexpr ostream& operator<<(ostream& os, pair<T, U> p) noexcept {
  os << p.first << " " << p.second;
  return os;
}
ostream& operator<<(ostream& os, mint m) {
  os << m.val();
  return os;
}
ostream& operator<<(ostream& os, modint m) {
  os << m.val();
  return os;
}

random_device seed_gen;
mt19937_64 engine(seed_gen());

struct BiCoef {
  vector<mint> fact_, inv_, finv_;
  BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
    fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
    for (int i = 2; i < n; i++) {
      fact_[i] = fact_[i - 1] * i;
      inv_[i] = -inv_[MOD % i] * (MOD / i);
      finv_[i] = finv_[i - 1] * inv_[i];
    }
  }
  mint c(ll n, ll k) const noexcept {
    if (n < k || n < 0 || k < 0) return 0;
    return fact_[n] * finv_[k] * finv_[n - k];
  }
  mint P(ll n, ll k) const noexcept { return c(n, k) * fact_[k]; }
  mint H(ll n, ll k) const noexcept { return c(n + k - 1, k); }
  mint Ch1(ll n, ll k) const noexcept {
    if (n < 0 || k < 0) return 0;
    mint res = 0;
    for (int i = 0; i < n; i++)
      res += c(n, i) * mint(n - i).pow(k) * (i & 1 ? -1 : 1);
    return res;
  }
  mint fact(ll n) const noexcept {
    if (n < 0) return 0;
    return fact_[n];
  }
  mint inv(ll n) const noexcept {
    if (n < 0) return 0;
    return inv_[n];
  }
  mint finv(ll n) const noexcept {
    if (n < 0) return 0;
    return finv_[n];
  }
};

BiCoef bc(500010);

#pragma endregion

template <typename T>
void icpc(T a) {
  if (!a) exit(0);
}
template <typename T, typename U>
void icpc(T a, U end) {
  if (a == end) exit(0);
}

#pragma region Matrix

// 参考・引用：https://qiita.com/gnbrganchan/items/47118d45b3af9d5ae9a4

using Type = modint;

struct Matrix {
  // 行列A
  vector<vector<Type>> A;
  // コンストラクタ:第1引数⇒行数、第2引数⇒列数、第3引数⇒初期値
  Matrix() : A() {}
  Matrix(int h, int w) : A(vector<vector<Type>>(h, vector<Type>(w))) {}
  Matrix(int h, int w, Type d)
      : A(vector<vector<Type>>(h, vector<Type>(w, d))) {}
  Matrix(vector<vector<Type>> A) : A(A) {}
  Matrix(initializer_list<initializer_list<Type>> A) : A(A.begin(), A.end()) {}
  // 添え字アクセス
  vector<Type> operator[](const int i) const { return A[i]; }
  vector<Type>& operator[](const int i) { return A[i]; }
  // 行数・列数
  int r = A.size();
  int c = (A.empty() ? 0 : A[0].size());
  // 行列同士の演算
  Matrix& operator+=(const Matrix& B) {
    assert(c == B.c && r == B.r);
    rep(i, r) rep(j, c) A[i][j] += B[i][j];
    return *this;
  }
  Matrix& operator-=(const Matrix& B) {
    assert(c == B.c && r == B.r);
    rep(i, r) rep(j, c) A[i][j] -= B[i][j];
    return *this;
  }
  Matrix& operator*=(const Matrix& B) {
    if (B.r == 1 and B.c == 1) {
      return (*this) *= B[0][0];
    } else if (r == 1 and c == 1) {
      Type k = A[0][0];
      (*this) = B;
      return (*this) *= k;
    }
    assert(c == B.r);
    Matrix m2(r, B.c, 0);
    rep(i, r) rep(j, B.c) rep(k, c) m2[i][j] += A[i][k] * B[k][j];
    c = B.c;
    rep(i, r) A[i].resize(c);
    rep(i, r) rep(j, c) A[i][j] = m2[i][j];
    return *this;
  }
  Matrix operator+(const Matrix& B) const { return Matrix(*this) += B; }
  Matrix operator-(const Matrix& B) const { return Matrix(*this) -= B; }
  Matrix operator*(const Matrix& B) const { return Matrix(*this) *= B; }
  vector<Type> operator*(const vector<Type>& b) const {
    assert(c == b.size());
    vector<Type> res(r);
    rep(i, r) rep(k, c) res[i] += A[i][k] * b[k];
    return res;
  }
  bool operator==(const Matrix& B) {
    assert(c == B.c && r == B.r);
    bool flg = true;
    rep(i, r) rep(j, c) if (A[i][j] != B[i][j]) flg = false;
    return flg;
  }
  // 行列とスカラの演算
  Matrix& operator+=(const Type& k) {
    rep(i, r) rep(j, c) A[i][j] += k;
    return *this;
  }
  Matrix& operator-=(const Type& k) {
    rep(i, r) rep(j, c) A[i][j] -= k;
    return *this;
  }
  Matrix& operator*=(const Type& k) {
    rep(i, r) rep(j, c) A[i][j] *= k;
    return *this;
  }
  Matrix& operator/=(const Type& k) {
    rep(i, r) rep(j, c) A[i][j] /= k;
    return *this;
  }
  Matrix operator+(const Type& k) const { return Matrix(*this) += k; }
  Matrix operator-(const Type& k) const { return Matrix(*this) -= k; }
  Matrix operator*(const Type& k) const { return Matrix(*this) *= k; }
  Matrix operator/(const Type& k) const { return Matrix(*this) /= k; }
  Matrix operator-() const { return Matrix(*this) *= -1; }
  // 回転（degの数だけ時計回りに90度回転）
  Matrix& rot(int deg) {
    Matrix m2(c, r);
    if (deg == 1 || deg == 3) {
      if (deg == 1) rep(i, r) rep(j, c) m2[j][r - i - 1] = A[i][j];
      if (deg == 3) rep(i, r) rep(j, c) m2[c - j - 1][i] = A[i][j];
      swap(c, r);  // 列数と行数を入れ替える
      A.resize(r);
      rep(i, r) A[i].resize(c);  //リサイズ
    }
    if (deg == 2) rep(i, r) rep(j, c) m2[r - i - 1][c - j - 1] = A[i][j];
    rep(i, r) rep(j, c) A[i][j] = m2[i][j];
    return *this;
  }
  // 転置
  Matrix& tran() {
    Matrix m2(c, r);
    rep(i, r) rep(j, c) m2[j][i] = A[i][j];
    (*this) = m2;
    return *this;
  }
  // 単位行列
  static Matrix E(int n) {
    Matrix res(n, n);
    rep(i, n) rep(j, n) res[i][j] = i == j;
    return res;
  }
  // 累乗
  Matrix pow(ll n) {
    assert(n >= 0);
    Matrix res = E(r);
    Matrix P = (*this);
    while (n > 0) {
      if (n & 1) res *= P;
      P *= P;
      n >>= 1;
    }
    return res;
  }
};
// 出力
ostream& operator<<(ostream& os, Matrix A) noexcept {
  rep(i, A.r) {
    if (i > 0) cout << "\n";
    rep(j, A.c) { cout << A[i][j] << (j + 1 == A.c ? "" : " "); }
  }
  return os;
}

#pragma endregion

Matrix A[26];

Matrix var(string&, int&);
Matrix expr(string&, int&);
Matrix term(string&, int&);
Matrix factor(string&, int&);
Matrix primary(string&, int&);
Matrix matrix(string&, int&);
Matrix row_seq(string&, int&);
Matrix row(string&, int&);
Matrix inum(string&, int&);

Matrix var(string& s, int& i) {
  assert(isupper(s[i]));
  return A[s[i++] - 'A'];
}

Matrix expr(string& s, int& i) {
  Matrix S = term(s, i);
  while (i < s.length() and (s[i] == '+' or s[i] == '-')) {
    if (s[i] == '+') {
      i++;
      S += term(s, i);
    } else {
      i++;
      S -= term(s, i);
    }
  }
  return S;
}

Matrix term(string& s, int& i) {
  Matrix P = factor(s, i);
  while (i < s.length() and s[i] == '*') {
    i++;
    P *= factor(s, i);
  }
  return P;
}

Matrix factor(string& s, int& i) {
  if (s[i] == '-') {
    i++;
    return -factor(s, i);
  }
  return primary(s, i);
}

// idnexed, transposed を兼ねる
Matrix primary(string& s, int& i) {
  Matrix P;
  if (isdigit(s[i])) {
    P = inum(s, i);
  } else if (isupper(s[i])) {
    P = var(s, i);
  } else if (s[i] == '[') {
    P = matrix(s, i);
  } else if (s[i] == '(') {
    i++;
    P = expr(s, i);
    i++;
  }
  while (s[i] == '(' or s[i] == '\'') {
    if (s[i] == '(') {
      i++;
      Matrix I = expr(s, i);
      assert(s[i++] == ',');
      Matrix J = expr(s, i);
      assert(s[i++] == ')');
      assert(I.r == 1);
      assert(J.r == 1);
      vector<vector<modint>> v;
      Matrix res(I.c, J.c);
      rep(i, I.c) rep(j, J.c) {
        res[i][j] = P.A[I[0][i].val() - 1][J[0][j].val() - 1];
      }
      P = res;
    } else if (s[i] == '\'') {
      i++;
      P.tran();
    }
  }
  return P;
}

Matrix matrix(string& s, int& i) {
  assert(s[i++] == '[');
  Matrix res = row_seq(s, i);
  assert(s[i++] == ']');
  return res;
}

Matrix row_seq(string& s, int& i) {
  Matrix P = row(s, i);
  vector<vector<modint>> v;
  rep(i, P.r) v.push_back(P.A[i]);
  while (i < s.length() and s[i] == ';') {
    i++;
    P = row(s, i);
    assert(v[0].size() == P.c);
    rep(i, P.r) v.push_back(P.A[i]);
  }
  return Matrix(v);
}

Matrix row(string& s, int& i) {
  Matrix P = expr(s, i);
  vector<vector<modint>> v = P.A;
  while (i < s.length() and s[i] == ' ') {
    i++;
    P = expr(s, i);
    assert(v.size() == P.r);
    rep(i, P.r) {
      rep(j, P.c) { v[i].push_back(P[i][j]); }
    }
  }
  return Matrix(v);
}

// digit を兼ねる
Matrix inum(string& s, int& i) {
  modint val = 0;
  while (i < s.length() and isdigit(s[i])) {
    val = val * 10 + s[i] - '0';
    i++;
  }
  return Matrix(1, 1, val);
}

void solve() {
  int n;
  cin >> n;
  cin.ignore();
  icpc(n);

  rep(i, n) {
    string s;
    getline(cin, s);
    int num = s[0] - 'A';
    s = s.substr(2);
    s.pop_back();
    int tmp = 0;
    A[num] = expr(s, tmp);
    cout << A[num] << "\n";
  }
  cout << "-----\n";
}

int main() {
  modint::set_mod(32768);
  while (1) solve();
}
accuracy: 1
time_ms: 100
memory_kb: 9372
final_rank: 20

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <cassert>
using namespace std;
using ll = long long;
using ull = unsigned long long;

vector<int> getchar_buffer;
int my_getchar(){
  if(getchar_buffer.size()){
    int res = getchar_buffer.back();
    getchar_buffer.pop_back();
    return res;
  }
  return getchar();
}

int readInt(){
  int n = 0;
  while(true){
    int c = my_getchar();
    if(c < '0' || '9' < c){
      getchar_buffer.push_back(c);
      break;
    }
    n = n * 10 + (c-'0');
  }
  return n;
}


const int modmask = 0x7fff;


struct Matrix{
  int H,W;
  vector<int> G;
  Matrix(int h,int w){
    H = h;
    W = w;
    G.assign(H*W,0);
  }
  int* operator[](int y){ return G.data() + (y*W); }
  const int* operator[](int y) const { return G.data() + (y*W); }

  void print() const {
    for(int y=0; y<H; y++){
      for(int x=0; x<W; x++){
        if(x) printf(" ");
        printf("%d",operator[](y)[x]);
      }
      printf("\n");
    }
  }
};

Matrix operator+(const Matrix& l, const Matrix& r){
  assert(l.H == r.H);
  assert(l.W == r.W);
  Matrix res(l.H,l.W);
  for(int y=0; y<l.H; y++) for(int x=0; x<l.W; x++) res[y][x] = (l[y][x] + r[y][x]) & modmask;
  return move(res);
}
Matrix operator-(const Matrix& l, const Matrix& r){
  assert(l.H == r.H);
  assert(l.W == r.W);
  Matrix res(l.H,l.W);
  for(int y=0; y<l.H; y++) for(int x=0; x<l.W; x++) res[y][x] = (l[y][x] + (modmask+1) - r[y][x]) & modmask;
  return move(res);
}
Matrix operator-(const Matrix& r){
  Matrix res(r.H,r.W);
  for(int y=0; y<r.H; y++) for(int x=0; x<r.W; x++) res[y][x] = ((modmask+1) - r[y][x]) & modmask;
  return move(res);
}
Matrix operator*(const Matrix& l, const Matrix& r){
  if(l.W == 1 && l.H == 1){
    Matrix res(r.H,r.W);
    for(int y=0; y<r.H; y++) for(int x=0; x<r.W; x++) res[y][x] = (l[0][0] * r[y][x]) & modmask;
    return move(res);
  }
  if(r.W == 1 && r.H == 1){
    Matrix res(l.H,l.W);
    for(int y=0; y<l.H; y++) for(int x=0; x<l.W; x++) res[y][x] = (l[y][x] * r[0][0]) & modmask;
    return move(res);
  }
  assert(l.W == r.H);
  Matrix res(l.H,r.W);
  for(int y=0; y<l.H; y++) for(int j=0; j<l.W; j++) for(int x=0; x<r.W; x++)
    res[y][x] = (res[y][x] + l[y][j] * r[j][x]) & modmask;
  return move(res);
}
Matrix matrix_catW(const Matrix& l, const Matrix& r){
  assert(l.H == r.H);
  Matrix res(l.H,l.W+r.W);
  for(int y=0; y<l.H; y++) for(int x=0; x<l.W; x++) res[y][x] = l[y][x];
  for(int y=0; y<r.H; y++) for(int x=0; x<r.W; x++) res[y][x+l.W] = r[y][x];
  return move(res);
}
Matrix matrix_catH(const Matrix& l, const Matrix& r){
  assert(l.W == r.W);
  Matrix res(l.H+r.H,l.W);
  for(int y=0; y<l.H; y++) for(int x=0; x<l.W; x++) res[y][x] = l[y][x];
  for(int y=0; y<r.H; y++) for(int x=0; x<r.W; x++) res[y+l.H][x] = r[y][x];
  return move(res);
}
Matrix matrix_trans(const Matrix& l){
  Matrix res(l.W,l.H);
  for(int y=0; y<l.W; y++) for(int x=0; x<l.H; x++) res[y][x] = l[x][y];
  return move(res);
}
Matrix matrix_index_primary(const Matrix& l, const Matrix& ipy, const Matrix& ipx){
  assert(ipy.H == 1);
  assert(ipx.H == 1);
  Matrix res(ipy.W,ipx.W);
  for(int y=0; y<ipy.W; y++) for(int x=0; x<ipx.W; x++) res[y][x] = l[ipy[0][y]-1][ipx[0][x]-1];
  return move(res);
}



Matrix readExp(const vector<Matrix>& A){
  vector<Matrix> st_operands;
  vector<int> st_operators;
  vector<int> st_primary_state = {0};
  bool prev_primary = false;

  auto reduce_operator = [&](int op)->bool{
    if(st_operators.empty()) return false;
    if(st_operators.back() != op) return false;
    st_operators.pop_back();
    //printf("reduce_operator(%c)\n",(char)op);
    do /* while(0) */ {
      if(op == '['){ break; }
      if(op == '('){ st_primary_state.pop_back(); break; }
      auto r = move(st_operands.back()); st_operands.pop_back();
      if(op == '_'){ st_operands.push_back(-r); continue; }
      auto l = move(st_operands.back()); st_operands.pop_back();
      if(op == ' '){ st_operands.push_back(matrix_catW(l,r)); break; }
      if(op == ';'){ st_operands.push_back(matrix_catH(l,r)); break; }
      if(op == '+'){ st_operands.push_back(l+r); break; }
      if(op == '-'){ st_operands.push_back(l-r); break; }
      if(op == '*'){ st_operands.push_back(l*r); break; }
      if(op == ','){ st_operands.push_back(l*r); break; }
    } while(0);
    return true;
  };

  bool done = false;
  while(!done){
    int nxc = my_getchar();
    assert(nxc != '\n');
    if(nxc == '.'){
      while(reduce_operator('_'));
      while(reduce_operator('*'));
      while(reduce_operator('+') || reduce_operator('-'));
      done = true;
    }
    else if(nxc == '('){
      if(prev_primary){
        //printf("index primary begins\n");
        st_primary_state.push_back(1);
        st_operators.push_back(nxc);
      }
      else{
        st_primary_state.push_back(0);
        st_operators.push_back(nxc);
      }
      prev_primary = false;
    }
    else if(nxc == ','){
      while(reduce_operator('_'));
      while(reduce_operator('*'));
      while(reduce_operator('+') || reduce_operator('-'));
      st_primary_state.back() = 2;
      prev_primary = false;
    }
    else if(nxc == ')'){
      if(st_primary_state.back() == 2){
        while(reduce_operator('_'));
        while(reduce_operator('*'));
        while(reduce_operator('+') || reduce_operator('-'));
        reduce_operator('(');
        Matrix ipx = move(st_operands.back()); st_operands.pop_back();
        Matrix ipy = move(st_operands.back()); st_operands.pop_back();
        st_operands.back() = matrix_index_primary(st_operands.back(), ipy, ipx);
        prev_primary = true;
      }
      else{
        while(reduce_operator('_'));
        while(reduce_operator('*'));
        while(reduce_operator('+') || reduce_operator('-'));
        reduce_operator('(');
      }
    }
    else if(nxc == ' '){
      while(reduce_operator('_'));
      while(reduce_operator('*'));
      while(reduce_operator('+') || reduce_operator('-'));
      while(reduce_operator(' '));
      st_operators.push_back(nxc);
      prev_primary = false;
    }
    else if(nxc == ';'){
      while(reduce_operator('_'));
      while(reduce_operator('*'));
      while(reduce_operator('+') || reduce_operator('-'));
      while(reduce_operator(' '));
      while(reduce_operator(';'));
      st_operators.push_back(nxc);
      prev_primary = false;
    }
    else if(nxc == '[') st_operators.push_back(nxc);
    else if(nxc == ']'){
      while(reduce_operator('_'));
      while(reduce_operator('*'));
      while(reduce_operator('+') || reduce_operator('-'));
      while(reduce_operator(' '));
      while(reduce_operator(';'));
      reduce_operator('[');
      prev_primary = true;
    }
    else if(nxc == '\''){
      st_operands.back() = matrix_trans(st_operands.back());
      prev_primary = true;
    }
    else if(nxc == '+'){
      while(reduce_operator('_'));
      while(reduce_operator('*'));
      while(reduce_operator('+') || reduce_operator('-'));
      st_operators.push_back(nxc);
      prev_primary = false;
    }
    else if(nxc == '-'){
      if(prev_primary){
        while(reduce_operator('_'));
        while(reduce_operator('*'));
        while(reduce_operator('+') || reduce_operator('-'));
        st_operators.push_back(nxc);
      }
      else{
        st_operators.push_back('_');
      }
      prev_primary = false;
    }
    else if(nxc == '*'){
      while(reduce_operator('_'));
      while(reduce_operator('*'));
      st_operators.push_back(nxc);
      prev_primary = false;
    }
    else if('0' <= nxc && nxc <= '9'){
      getchar_buffer.push_back(nxc);
      int nxval = readInt();
      st_operands.push_back(Matrix(1,1));
      st_operands.back()[0][0] = nxval;
      prev_primary = true;
    }
    else if('A' <= nxc && nxc <= 'Z'){
      st_operands.push_back(A[nxc-'A']);
      prev_primary = true;
    }
    /*
    printf("############################\n");
    for(auto a : st_operands){
      a.print();
      printf("- - - - - - - - - - - \n");
    }
    for(auto a : st_operators){
      printf("%c",(char)a);
    }
      printf("\n- - - - - - - - - - - \n");
    fflush(stdout);
    */
  }
  //  printf("############################\n");
  return move(st_operands.back());
}



bool testcase(){
  int n = readInt();
  int newline_after_n = my_getchar(); assert(newline_after_n == '\n');
  if(n == 0) return false;
  vector<Matrix> A(26,Matrix(1,1));
  for(int i=0; i<n; i++){
    int assign_dst = my_getchar() - 'A';
    int assign_equal = my_getchar(); assert(assign_equal == '=');
    A[assign_dst] = readExp(A);
    A[assign_dst].print();
    int assign_newline = my_getchar(); assert(assign_newline == '\n');
  }
  printf("-----\n");
  return true;
}



int main(){
  while(testcase());
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3608
final_rank: 4

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 32768;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 2;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

typedef complex<ld> Point;
ld dot(Point a, Point b) { return real(conj(a) * b); }
ld cross(Point a, Point b) { return imag(conj(a) * b); }
namespace std {
	bool operator<(const Point& lhs, const Point& rhs) {
		return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real();
	}
}
struct Line {
	Point a, b;
};
struct Circle {
	Point p; ld r;
};
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps)return 1;//counter clockwise
	if (cross(b, c) < -eps)return -1;//clock wise
	if (dot(b, c) < 0)return 2;//c--a--b on line
	if (norm(b) < norm(c))return -2;//a--b--c on line
	return 0; //a--c--b on line
}
bool isis_ss(Line s, Line t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}

//点を直線で反転
Point rev_lp(Line l, Point p) {
	Point h = proj(l, p);
	return h + h - p;
}
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a; Point tv = t.b - t.a;
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

using mat = vector<vector<modint>>;

mat memo[26];

mat expr(string& s, int& i);
mat term(string& s, int& i);
mat factor(string& s, int& i);
mat primary(string& s, int& i);
mat inum(string& s, int& i);
mat matrix(string& s, int& i);
mat row_seq(string& s, int& i);
mat row(string& s, int& i);

mat expr(string& s, int& i) {
	mat res = term(s, i);
	while (s[i] == '+' || s[i] == '-') {
		modint c = 1; if (s[i] == '-')c = -1;
		i++;
		mat nex = term(s, i);
		assert(res.size() == nex.size() && res[0].size() == nex[0].size());
		rep(i, res.size())rep(j, res[i].size())res[i][j] += c * nex[i][j];
	}
	return res;
}
mat term(string& s, int& i) {
	mat res = factor(s, i);
	while (s[i] == '*') {
		i++;
		mat nex = factor(s, i);
		if (res[0].size() != nex.size()) {
			if (res.size() == 1 && res[0].size() == 1) {
				swap(res, nex);
				rep(i, res.size())rep(j, res[i].size()) {
					res[i][j] *= nex[0][0];
				}
			}
			else if (nex.size() == 1 && nex[0].size() == 1) {
				rep(i, res.size())rep(j, res[i].size()) {
					res[i][j] *= nex[0][0];
				}
			}
			else {
				assert(false);
			}
		}
		else {
			int n = res.size(), m = nex[0].size();
			mat nres(n, vector<modint>(m));
			rep(i, n)rep(j, m) {
				rep(k, res[i].size()) {
					nres[i][j] += res[i][k] * nex[k][j];
				}
			}
			swap(res, nres);
		}
	}
	return res;
}
mat factor(string& s, int& i) {
	if (s[i] == '-') {
		i++;
		mat res = factor(s, i);
		rep(i, res.size())rep(j, res[i].size())res[i][j] *= -1;
		return res;
	}
	return primary(s, i);
}
mat primary(string& s, int& i) {
	mat res;
	if ('0' <= s[i] && s[i] <= '9') {
		res = inum(s, i);
	}
	else if ('A' <= s[i] && s[i] <= 'Z') {
		res = memo[s[i] - 'A']; i++;
	}
	else if (s[i] == '[') {
		res = matrix(s, i);
	}
	else if (s[i] == '(') {
		i++;
		res = expr(s, i);
		i++;
	}
	else {
		cout << s << " " << i << "\n";
		assert(false);
	}
	while (s[i] == '(' || s[i] == '\'') {
		if (s[i] == '(') {
			i++;
			mat n1 = expr(s, i);
			i++;
			mat n2 = expr(s, i);
			i++;
			assert(n1.size() == 1 && n2.size() == 1);
			int n = n1[0].size();
			int m = n2[0].size();
			mat nres(n, vector<modint>(m));
			rep(i, n)rep(j, m) {
				int x = n1[0][i] - (modint)1;
				int y = n2[0][j] - (modint)1;
				assert(x < res.size() && y < res[0].size());
				nres[i][j] = res[n1[0][i] - (modint)1][n2[0][j] - (modint)1];
			}
			swap(res, nres);
		}
		else {
			i++;
			int n = res.size();
			int m = res[0].size();
			mat nres(m, vector<modint>(n));
			rep(i, m)rep(j, n) {
				nres[i][j] = res[j][i];
			}
			swap(res, nres);
		}
	}
	return res;
}


mat matrix(string& s, int& i) {
	i++;
	mat res = row_seq(s, i);
	i++;
	return res;
}
mat row_seq(string& s, int& i) {
	mat res = row(s, i);
	while (s[i] == ';') {
		i++;
		mat nex = row(s, i);
		assert(res[0].size() == nex[0].size());
		rep(j, nex.size())res.push_back(nex[j]);
	}
	return res;
}
mat row(string& s, int& i) {
	mat res = expr(s, i);
	while (s[i] == ' ') {
		i++;
		mat nex = expr(s, i);
		assert(res.size() == nex.size());
		rep(i, res.size()) {
			rep(j, nex[i].size()) {
				res[i].push_back(nex[i][j]);
			}
		}
	}
	return res;
}
mat inum(string& s, int& i) {
	modint val = 0;
	while ('0' <= s[i] && s[i] <= '9') {
		val = val * (modint)10 + (modint)(s[i] - '0');
		i++;
	}
	mat res = { {val} };
	return res;
}

int n;
void solve() {
	string s;
	getline(cin, s);
	rep(_, n) {
		getline(cin, s);
		int c = s[0] - 'A';
		s.erase(s.begin(), s.begin() + 2);
		int i = 0;
		mat ans = expr(s, i);
		memo[c] = ans;
		rep(i, ans.size()) {
			rep(j, ans[i].size()) {
				if (j > 0)cout << " ";
				cout << ans[i][j];
			}
			cout << "\n";
		}
	}
	cout << "-----\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t;rep(i,t)
	while (cin >> n, n)
		solve();
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4048
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
#define var auto

const char newl = '\n';

template<typename T1, typename T2>
inline bool chmin(T1 &a, T2 b) { bool c = a > b; if (c) a = b; return c; }
template<typename T1, typename T2>
inline bool chmax(T1 &a, T2 b) { bool c = a < b; if (c) a = b; return c; }

//BEGIN CUT HERE
template<typename T, T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T, T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T, T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}
//END CUT HERE

//BEGIN CUT HERE
template<typename K>
struct Matrix{
  typedef vector<K> arr;
  typedef vector<arr> mat;
  size_t r, c;
  mat dat;

  Matrix(){}
  Matrix(size_t r,size_t c):dat(r,arr(c,K())),r(r),c(c){}
  Matrix(mat dat):dat(dat),r(dat.size()),c(dat[0].size()){}

  size_t size() const{return dat.size();}
  bool empty() const{return size()==0;}
  arr& operator[](size_t k){return dat[k];}
  const arr& operator[](size_t k) const {return dat[k];}

  const void operator+=(Matrix<K>& b){
    for (int i = 0; i < r; i++){
      for (int j = 0; j < c; j++){
        dat[i][j] += b[i][j];
      }
    }
  }
  const Matrix<K> operator+(Matrix<K>& b){
    var res = Matrix<K>(dat);
    res += b;
    return res;
  }
  const void operator-=(Matrix<K>& b){
    for (int i = 0; i < r; i++){
      for (int j = 0; j < c; j++){
        dat[i][j] -= b[i][j];
      }
    }
  }
  const Matrix<K> operator-(Matrix<K>& b){
    var res = Matrix<K>(dat);
    res -= b;
    return res;
  }

  const void operator*=(K& b){
    for (int i = 0; i < r; i++){
      for (int j = 0; j < c; j++){
        dat[i][j] *= b;
      }
    }
  }

  static Matrix cross(const Matrix &A,const Matrix &B){
    Matrix res(A.size(),B[0].size());
    for(int i=0;i<(int)A.size();i++)
      for(int j=0;j<(int)B[0].size();j++)
        for(int k=0;k<(int)B.size();k++)
          res[i][j]+=A[i][k]*B[k][j];
    return res;
  }



  Matrix<K> transpose(){
    Matrix<K> res(c, r);
    for (int i = 0; i < r; i++){
      for (int j = 0; j < c; j++){
        res[j][i] = dat[i][j];
      }
    }
    return res;
  }
};
//END CUT HERE

using M = Mint<int, 32768>;
using Mat = Matrix<M>;

map<char, Mat> mats;

//A = expr
pair<char, Mat> assignment(string&, int&);
//term+term-term+...
Mat expr(string&, int&);
//primary*primary*...
Mat term(string&, int&);
//---...
//num/variable/matrix
//(transposed or indexed)...
Mat primary(string&, int&);
Mat matrix(string&, int&);

pair<char, Mat> assignment(string& s, int& i){
  assert(isalpha(s[i]));
  var variable = s[i];
  i++;
  assert(s[i] == '=');
  i++;
  var value = expr(s, i);
  return pair<char, Mat>(variable, value);
}

Mat expr(string& s, int& i){
  var res = term(s, i);
  while (i < s.size() && (s[i] == '+' || s[i] == '-')){
    var op = s[i];
    i++;
    var nxt = term(s, i);
    res = op == '+' ? res + nxt : res - nxt;
  }
  return res;
}

Mat term(string& s, int& i){
  var res = primary(s, i);
  while (i < s.size() && s[i] == '*'){
    i++;
    var nxt = primary(s, i);
    if (res.r == 1 && res.c == 1){
      nxt *= res.dat[0][0];
      res = nxt;
    }
    else if (nxt.r == 1 && nxt.c == 1){
      res *= nxt.dat[0][0];
    }
    else res = Mat::cross(res, nxt);
  }
  return res;
}

Mat primary(string& s, int& i){
  ll sign = 1;
  while (s[i] == '-'){
    sign *= -1;
    i++;
  }
  Mat res;
  if (isdigit(s[i])){
    ll num = 0;
    while (i < s.size() && isdigit(s[i])){
      num = num * 10 + s[i] - '0';
      i++;
    }
    res = Mat(1, 1);
    res[0][0] = M(num);
  }
  else if (isalpha(s[i])){
    res = mats[s[i]];
    i++;
  }
  else if (s[i] == '('){
    i++;
    res = expr(s, i);
    assert(s[i] == ')'); i++;
  }
  else{
    res = matrix(s, i);
  }
  while (i < s.size()){
    //O(nm) 100*100
    if (s[i] == '\''){
      res = res.transpose();
      i++;
      continue;
    }
    if (s[i] == '('){
      i++;
      var a = expr(s, i);
      assert(s[i] == ','); i++;
      var b = expr(s, i);
      assert(s[i] == ')'); i++;
      assert(a.r == 1 && b.r == 1);

      Mat k(a.c, b.c);
      for (int i = 0; i < k.r; i++){
        for (int j = 0; j < k.c; j++){
          k[i][j] = res[a[0][i].v - 1][b[0][j].v - 1];
        }
      }

      res = k;
      continue;
    }
    break;
  }
  for (int i = 0; i < res.r; i++){
    for (int j = 0; j < res.c; j++){
      res[i][j] = res[i][j] * M(sign);
    }
  }
  return res;
}

Mat matrix(string& s, int& i){
  assert(s[i] == '['); i++;
  vector<vector<M>> res;
  while (true){
    int baserow = -1;
    bool isfirst = true;
    while (true){
      var row = expr(s, i);
      if (isfirst){
        baserow = res.size();
        for (int i = 0; i < row.r; i++){
          res.push_back(vector<M>{});
        }
        isfirst = false;
      }
      for (int i = 0; i < row.r; i++){
        for (int j = 0; j < row.c; j++){
          res[baserow + i].emplace_back(row[i][j]);
        }
      }
      if (s[i] == ' '){
        i++;
        continue;
      }
      else break;
    }
    if (s[i] == ';'){
      i++;
      continue;
    }
    else break;
  }
  assert(s[i] == ']'); i++;
  return res;
}

void dump(Mat m){
  for (int i = 0; i < m.r; i++){
    for (int j = 0; j < m.c; j++){
      if (j != 0) cout << " ";
      cout << m[i][j];
    }
    cout << endl;
  }
}

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  int n;
  while (cin >> n, n){
    cin.ignore();
    for (int iter = 0; iter < n; iter++){
      string s;
      getline(cin, s);
      int i = 0;
      var [variable, value] = assignment(s, i);
      dump(value);
      mats[variable] = value;
    }
    cout << "-----" << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3672
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define MOD 32768LL
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef vector<ll> vec;
typedef vector<vec> mat;

class val{
public:
	mat m;
	ll v;
	int t;
	val(){
		t=0;
		v=0;
	}

	val(int tt,ll vv){
		t=tt;
		v=vv;
	}

	val(mat mm){
		t=1;
		m=mm;
		for(int i=0;i<m.size();i++){
			for(int j=0;j<m[0].size();j++){
				m[i][j]%=MOD;
				if(m[i][j]<0LL)m[i][j]+=MOD;
			}
		}
	}
	val(ll vv){
		v=vv;
		v%=MOD;
		if(v<0LL){
			v+=MOD;
		}
		t=0;
	}
	val operator+ (val va){
		if(va.t==1 && va.m.size()==1 && va.m[0].size()==1){
			va.t=0;
			va.v=va.m[0][0];
		}
		if(t==1 && m.size()==1 && m[0].size()==1){
			t=0;
			v=m[0][0];
		}
		if(t==0 && va.t==0){
			return val(va.v+v);
		}
		if(t==0 && va.t==1){
			for(int i=0;i<va.m.size();i++){
				for(int j=0;j<va.m[0].size();j++){
					va.m[i][j]+=v;
				}
			}
			return mat(va.m);
		}
		if(t==1 && va.t==0){
			for(int i=0;i<m.size();i++){
				for(int j=0;j<m[0].size();j++){
					m[i][j]+=va.v;
				}
			}
			return mat(m);
		}
		if(t==1 && va.t==1){
			for(int i=0;i<va.m.size();i++){
				for(int j=0;j<va.m[0].size();j++){
					m[i][j]+=va.m[i][j];
				}
			}
			return mat(m);
		}
	}
	val operator- (val va){
		if(va.t==1 && va.m.size()==1 && va.m[0].size()==1){
			va.t=0;
			va.v=va.m[0][0];
		}
		if(t==1 && m.size()==1 && m[0].size()==1){
			t=0;
			v=m[0][0];
		}
		if(t==0 && va.t==0){
			return val(v-va.v);
		}
		if(t==0 && va.t==1){
			for(int i=0;i<va.m.size();i++){
				for(int j=0;j<va.m[0].size();j++){
					va.m[i][j]=v-va.m[i][j];
				}
			}
			return mat(va.m);
		}
		if(t==1 && va.t==0){
			for(int i=0;i<m.size();i++){
				for(int j=0;j<m[0].size();j++){
					m[i][j]-=va.v;
				}
			}
			return mat(m);
		}
		if(t==1 && va.t==1){
			for(int i=0;i<va.m.size();i++){
				for(int j=0;j<va.m[0].size();j++){
					m[i][j]-=va.m[i][j];
				}
			}
			return mat(m);
		}
	}
	val operator* (val va){
		if(va.t==1 && va.m.size()==1 && va.m[0].size()==1){
			va.t=0;
			va.v=va.m[0][0];
		}
		if(t==1 && m.size()==1 && m[0].size()==1){
			t=0;
			v=m[0][0];
		}
		if(t==0 && va.t==0){
			return val(v*va.v);
		}
		if(t==0 && va.t==1){
			for(int i=0;i<va.m.size();i++){
				for(int j=0;j<va.m[0].size();j++){
					va.m[i][j]=v*va.m[i][j];
				}
			}
			return mat(va.m);
		}
		if(t==1 && va.t==0){
			for(int i=0;i<m.size();i++){
				for(int j=0;j<m[0].size();j++){
					m[i][j]*=va.v;
				}
			}
			return mat(m);
		}
		if(t==1 && va.t==1){
			mat C(m.size(),vec(va.m[0].size()));
			for(int i=0;i<m.size();i++){
				for(int k=0;k<va.m.size();k++){
					for(int j=0;j<va.m[0].size();j++){
						C[i][j]=(C[i][j]+(m[i][k]*va.m[k][j]%MOD))%MOD;
					}
				}
			}
			return mat(C);
		}
	}
};

val v[35];

typedef string::const_iterator State;
val expression(State &begin);

int number(State &begin){
	int ret=0;
	while(isdigit(*begin)){
		ret*=10;
		ret+=*begin-'0';
		ret%=32768LL;
		begin++;
	}
	return ret;
}

val row(State &begin){
	val ret=expression(begin);
	if(*begin==' '){
		begin++;
		val v2=row(begin);
		//printf("%d %d\n",ret.t,v2.t);
		if(v2.t==0 && ret.t==0){
			ret.t=1;
			ret.m=mat(1,vec(2));
			ret.m[0][0]=ret.v;
			ret.m[0][1]=v2.v;
		}else if(v2.t==0){
			ret.m[0].push_back(v2.v);
		}else if(ret.t==0){
			ret.t=1;
			ret.m=mat(1,vec(1));
			ret.m[0][0]=ret.v;
			for(int i=0;i<v2.m[0].size();i++){
				ret.m[0].push_back(v2.m[0][i]);
			}
		}else if(ret.t==1 && v2.t==1){
			//printf("%d %d %d %d\n",ret.m.size(),ret.m[0].size(),v2.m.size(),v2.m[0].size());
			for(int i=0;i<v2.m.size();i++){
				for(int j=0;j<v2.m[i].size();j++){
					ret.m[i].push_back(v2.m[i][j]);
				}
			}
		}
		return ret;
	}else{
		return ret;
	}
}

val rowsqr(State &begin){
	val ret=row(begin);
	while(1){
		//cout << "rs " << *begin << endl;
		if(*begin==';'){
			begin++;
			val v2=rowsqr(begin);
			if(ret.t==0){
				ret.t=1;
				ret.m=mat(1,vec(1));
				ret.m[0][0]=ret.v;
			}
			if(v2.t==0){
				ret.m.push_back(vec(1,v2.v));
			}else{
				for(int i=0;i<v2.m.size();i++){
					ret.m.push_back(v2.m[i]);
				}
			}
			//printf("%d %d\n",ret.m.size(),ret.m[0].size());
		}else{
			return ret;
		}
	}
	
}

val primary(State &begin){
	val ret=val(-1,0);
	while(1){
		if(*begin=='['){
			begin++;
			ret=rowsqr(begin);
			begin++;
		}else if((*begin)>='A' && (*begin)<='Z'){
			ret=v[(*begin)-'A'];
			begin++;
		}else if(*begin=='('){
			begin++;
			val v1=expression(begin);
			if(*begin==')'){
				begin++;
				ret=v1;
				continue;
			}
			begin++;
			val v2=expression(begin);
			begin++;
			val ret2;
			ret2.t=1;
			if(ret.t==0){
				ret.m=mat(1,vec(1,ret.v));
			}
			if(v1.t==0){
				v1.m=mat(1,vec(1,v1.v));
			}
			if(v2.t==0){
				v2.m=mat(1,vec(1,v2.v));
			}
			ret2.m=mat(v1.m[0].size(),vec(v2.m[0].size()));
			for(int i=0;i<v1.m[0].size();i++){
				for(int j=0;j<v2.m[0].size();j++){
					ret2.m[i][j]=ret.m[v1.m[0][i]-1][v2.m[0][j]-1];
				}
			}
			ret=ret2;
		}else if(*begin=='\''){
			begin++;
			val ret2;
			ret2.t=ret.t;
			if(ret.t==0){
				ret2.v=ret.v;
			}else if(ret.t==1){
				ret2.m=mat(ret.m[0].size(),vec(ret.m.size()));
				for(int i=0;i<ret.m.size();i++){
					for(int j=0;j<ret.m[0].size();j++){
						ret2.m[j][i]=ret.m[i][j];
					}
				}
			}
			ret=ret2;
		}else if(isdigit(*begin)){
			ret=val(number(begin));
		}else{
			break;
		}
	}
	return ret;
}

val negation(val ret){
	if(ret.t==0){
		ret.v=MOD-ret.v;
		return ret;
	}else{
		for(int i=0;i<ret.m.size();i++){
			for(int j=0;j<ret.m[i].size();j++){
				ret.m[i][j]=MOD-ret.m[i][j];
			}
		}
		return ret;
	}
}

val factor(State &begin){
	if(*begin=='-'){
		begin++;
		val ret=factor(begin);
		return negation(ret);
	}else{
		return primary(begin);
	}
}

val term(State &begin){
	val ret=factor(begin);
	while(1){
		if(*begin=='*'){
			begin++;
			ret=ret*factor(begin);
		}else{
			break;
		}
	}
	return ret;
}

val expression(State &begin){
	val ret=term(begin);
	while(1){
		if(*begin=='+'){
			begin++;
			ret=ret+term(begin);
		}else if(*begin=='-'){
			begin++;
			ret=ret-term(begin);
		}else{
			break;
		}
	}
	return ret;
}

int n;

void solve(){
	for(int i=0;i<26;i++){
		v[i].m.clear();
		v[i].t=0;
	}
	for(int i=0;i<n;i++){
		string str;
		getline(cin,str);
		State b=str.begin();
		b++;
		b++;
		int pos=str[0]-'A';
		v[pos]=expression(b);
		if(v[pos].t==0){
			printf("%lld\n",v[pos].v);
		}else{
			for(int i=0;i<v[pos].m.size();i++){
				for(int j=0;j<v[pos].m[0].size();j++){
					printf("%lld%c",v[pos].m[i][j],j+1==v[pos].m[0].size()?'\n':' ');
				}
			}
		}
	}
	printf("-----\n");
}

int main(void){
	while(1){
		scanf("%d%*c",&n);
		if(n==0)break;
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3732
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
//#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define MOD 32768
typedef vector<int> V;
typedef vector<V> MATRIX;

int N;
int global_index;
char buf[105];
MATRIX TABLE[26];

MATRIX expr();

MATRIX operator+(const MATRIX &A,const MATRIX &B){

	int num_row = A.size();
	int num_col = A[0].size();

	MATRIX RET(num_row,V(num_col));

	for(int row = 0; row < num_row; row++){
		for(int col = 0; col < num_col; col++){
			RET[row][col] = A[row][col]+B[row][col];
			RET[row][col] %= MOD;
		}
	}

	return RET;
}

MATRIX operator-(const MATRIX &A,const MATRIX &B){

	int num_row = A.size();
	int num_col = A[0].size();

	MATRIX RET(num_row,V(num_col));

	for(int row = 0; row < num_row; row++){
		for(int col = 0; col < num_col; col++){
			RET[row][col] = A[row][col]-B[row][col];
			RET[row][col] = (RET[row][col]+MOD)%MOD;
		}
	}

	return RET;
}

MATRIX operator*(const MATRIX &A, const MATRIX &B){

	int num_rowA = A.size();
	int num_colA = A[0].size();

	int num_rowB = B.size();
	int num_colB = B[0].size();

	if(num_rowA == 1 && num_colA == 1){ //Aがスカラー

		MATRIX RET(num_rowB,V(num_colB));

		for(int row = 0; row < num_rowB; row++){
			for(int col = 0; col < num_colB; col++){
				RET[row][col] = B[row][col]*A[0][0];
				RET[row][col] %= MOD;
			}
		}

		return RET;

	}else if(num_rowB == 1 && num_colB == 1){ //Bがスカラー

		MATRIX RET(num_rowA,V(num_colA));

		for(int row = 0; row < num_rowA; row++){
			for(int col = 0; col < num_colA; col++){
				RET[row][col] = A[row][col]*B[0][0];
				RET[row][col] %= MOD;
			}
		}

		return RET;

	}else{

		MATRIX RET(num_rowA,V(num_colB));

		for(int row = 0; row < num_rowA; row++){
			for(int col = 0; col < num_colB; col++){
				RET[row][col] = 0;
				for(int a = 0; a < num_colA; a++){
					RET[row][col] += A[row][a]*B[a][col];
					RET[row][col] %= MOD;
				}
			}
		}

		return RET;
	}
}

MATRIX operator-(const MATRIX &A){


	int num_rowA = A.size();
	int num_colA = A[0].size();
	MATRIX RET(num_rowA,V(num_colA));

	for(int row = 0; row < num_rowA; row++){
		for(int col = 0; col < num_colA; col++){
			RET[row][col] = (-A[row][col]+MOD)%MOD;
		}
	}
	return RET;
}

MATRIX transpose(MATRIX A){

	int num_row = A[0].size();
	int num_col = A.size();

	MATRIX RET(num_row,V(num_col));

	for(int row = 0; row < A.size(); row++){
		for(int col = 0; col < A[0].size(); col++){
			RET[col][row] = A[row][col];
		}
	}

	return RET;
}

MATRIX get_row(){

	MATRIX A = expr();

	while(buf[global_index] == ' '){
		global_index++;
		MATRIX B = expr();
		for(int a = 0; a < A.size(); a++){
			A[a].insert(A[a].end(),B[a].begin(),B[a].end());
		}
	}
	return A;
}


MATRIX row_seq(){
	MATRIX A = get_row();

	while(buf[global_index] == ';'){
		global_index++;
		MATRIX B = get_row();
		A.insert(A.end(),B.begin(),B.end());
	}

	return A;
}

MATRIX matrix(){

	global_index++;
	MATRIX A = row_seq();
	global_index++;

	return A;
}

MATRIX get_var(){

	MATRIX RET = TABLE[buf[global_index]-'A'];
	global_index++;

	return RET;
}

MATRIX inum(){

	int tmp = 0;

	while(buf[global_index] >= '0' && buf[global_index] <= '9'){
		tmp = 10*tmp+(buf[global_index]-'0');
		tmp %= MOD;
		global_index++;
	}

	MATRIX RET(1,V(1));

	RET[0][0] = tmp;

	return RET;
}



MATRIX primary(){

	MATRIX A;

	if(buf[global_index] >= '0' && buf[global_index] <= '9'){

		A = inum();

	}else if(buf[global_index] >= 'A' && buf[global_index] <= 'Z'){

		A = get_var();

	}else if(buf[global_index] == '['){

		A = matrix();

	}else if(buf[global_index] == '('){
		global_index++;
		A = expr();
		global_index++;
	}

	bool FLG;

	while(true){
		FLG = false;

		if(buf[global_index] == '('){

			FLG = true;
			global_index++;
			MATRIX B = expr();
			global_index++;
			MATRIX C = expr();
			global_index++;

			int num_row = B[0].size();
			int num_col = C[0].size();

			MATRIX TMP(num_row,V(num_col));

			for(int row = 0; row < num_row; row++){
				for(int col = 0; col < num_col; col++){
					TMP[row][col] = A[B[0][row]-1][C[0][col]-1];
				}
			}
			A = TMP;

		}else if(buf[global_index] == '\''){
			FLG = true;
			global_index++;
			A = transpose(A);
		}

		if(!FLG)break;
	}
	return A;
}


MATRIX factor(){

	if(buf[global_index] == '-'){

		global_index++;
		return -factor();

	}else{

		return primary();
	}
}

MATRIX term(){

	MATRIX A = factor();

	while(buf[global_index] == '*'){
		global_index++;
		A = A*factor();
	}
	return A;
}

MATRIX expr(){

	MATRIX A = term();
	char op;

	while(buf[global_index] == '+' || buf[global_index] == '-'){

		op = buf[global_index++];

		if(op == '+'){

			A = A+term();

		}else{

			A = A-term();
		}
	}

	return A;
}

void assignment(){

	int type = buf[0]-'A';
	global_index = 2;
	TABLE[type] = expr();

	global_index++;
}

void func(){

	getchar();
	for(int loop = 0; loop < N; loop++){
		fgets(buf,100,stdin);

		assignment();

		MATRIX A = TABLE[buf[0]-'A'];
		int num_row = A.size();
		int num_col = A[0].size();

		for(int row = 0; row < num_row; row++){
			printf("%d",A[row][0]);
			for(int col = 1; col < num_col; col++){
				printf(" %d",A[row][col]);
			}
			printf("\n");
		}
	}
	printf("-----\n");
}


int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3380
final_rank: 2

code_snippet: #include <cstdio>
#include <cstdint>
#include <cctype>
#include <cassert>
#include <vector>
#include <algorithm>
#include <string>
#include <map>

#define fprintf(...) void(0)

const int M=32768;

class Matrix {
  size_t r=0, c=0;
  std::vector<std::vector<int>> entity;
  
public:
  Matrix(): entity(0) {}
  Matrix(int x): r(1), c(1), entity(1, std::vector<int>(1, x)) {}
  Matrix(size_t r, size_t c): r(r), c(c), entity(r, std::vector<int>(c)) {}
  Matrix(const Matrix &oth): r(oth.r), c(oth.c), entity(oth.entity) {}
  Matrix(Matrix &&oth): r(oth.r), c(oth.c), entity(std::move(oth.entity)) {}

  Matrix &operator =(const Matrix &oth) {
    r = oth.r;
    c = oth.c;
    entity = oth.entity;
    return *this;
  }

  Matrix &operator =(Matrix &&oth) {
    r = oth.r;
    c = oth.c;
    entity = std::move(oth.entity);
    return *this;
  }

  Matrix &operator +=(const Matrix &oth) {
    assert(r == oth.r && c == oth.c);
    for (size_t i=0; i<r; ++i)
      for (size_t j=0; j<c; ++j) {
        entity[i][j] += oth[i][j];
        if (entity[i][j] >= M) entity[i][j] -= M;
      }

    return *this;
  }

  Matrix operator +(const Matrix &oth) const {
    return Matrix(*this) += oth;
  }

  Matrix &operator -=(const Matrix &oth) {
    assert(r == oth.r && c == oth.c);
    for (size_t i=0; i<r; ++i)
      for (size_t j=0; j<c; ++j) {
        entity[i][j] -= oth[i][j];
        if (entity[i][j] < 0) entity[i][j] += M;
      }

    return *this;
  }

  Matrix operator -(const Matrix &oth) const {
    return Matrix(*this) -= oth;
  }

  Matrix operator *(const Matrix &oth) const {
    if (oth.r == 1 && oth.c == 1) {
      Matrix res(*this);
      for (size_t i=0; i<r; ++i)
        for (size_t j=0; j<c; ++j)
          res[i][j] = res[i][j]*oth[0][0] % M;

      return res;
    }
    if (r == 1 && c == 1) {
      Matrix res(oth);
      for (size_t i=0; i<oth.r; ++i)
        for (size_t j=0; j<oth.c; ++j)
          res[i][j] = res[i][j]*entity[0][0] % M;

      return res;
    }
    assert(c == oth.r);
    Matrix res(r, oth.c);
    for (size_t i=0; i<r; ++i)
      for (size_t j=0; j<c; ++j)
        for (size_t k=0; k<oth.c; ++k) {
          res[i][k] += entity[i][j] * oth[j][k];
          if ((res[i][k] %= M) < 0) res[i][k] += M;
        }

    return res;
  }

  Matrix &operator *=(const Matrix &oth) {
    Matrix rhs=(*this)*oth;
    return (*this = rhs);
  }

  const std::vector<int> &operator [](size_t i) const {
    return entity[i];
  }

  std::vector<int> &operator [](size_t i) {
    return entity[i];
  }

  Matrix operator [](
      const std::pair<std::vector<int>, std::vector<int>> &ind) const {

    size_t ir=ind.first.size(), ic=ind.second.size();
    Matrix res(ir, ic);
    for (size_t i=0; i<ir; ++i)
      for (size_t j=0; j<ic; ++j)
        res[i][j] = entity[ind.first[i]-1][ind.second[j]-1];

    return res;
  }

  Matrix operator -() const {
    Matrix res(r, c);
    for (size_t i=0; i<r; ++i)
      for (size_t j=0; j<c; ++j)
        if (entity[i][j])
          res[i][j] = M-entity[i][j];

    return res;
  }

  Matrix operator ~() const {
    Matrix res(c, r);
    for (size_t i=0; i<r; ++i)
      for (size_t j=0; j<c; ++j)
        res[j][i] = entity[i][j];

    return res;
  }

  size_t row() const {
    return entity.size();
  }

  size_t col() const {
    return entity[0].size();
  }

  void add_row() {
    entity.emplace_back();
    ++r;
  }

  void add_col(size_t i, int x) {
    entity[i].push_back(x);
    if (c < entity[i].size())
      c = entity[i].size();
  }

  void output() const {
    for (size_t i=0; i<r; ++i)
      for (size_t j=0; j<c; ++j)
        printf("%d%c", entity[i][j], j+1<c? ' ':'\n');
  }
};

Matrix parse(
    const std::string &s, size_t &i, const std::map<char, Matrix> &vars,
    size_t preced=0) {

  static const std::vector<std::string> &ops={"+-", "*"};

  fprintf(stderr, "s[%zu]: %c #%zu\n", i, s[i], preced);
  if (preced == ops.size()) {
    if (s[i] == '-') {
      return -parse(s, ++i, vars, preced);
    }

    Matrix res;
    if (isdigit(s[i])) {
      int scl=s[i]-'0';
      while (++i < s.length() && isdigit(s[i]))
        scl = scl*10+s[i]-'0';
      if ((scl %= M) < 0) scl += M;
      res = Matrix(scl);
    } else if (isupper(s[i])) {
      res = vars.at(s[i++]);
    } else if (s[i] == '(') {
      res = parse(s, ++i, vars, 0);
      assert(s[i] == ')');
      ++i;
    } else if (s[i] == '[') {
      // tsurai
      ++i;
      size_t r=0, c=0;
      while (s[i] != ']') {
        Matrix tmp=parse(s, i, vars, 0);
        for (size_t ir=0; ir<tmp.row(); ++ir) {
          if (r+ir >= res.row()) res.add_row();
          for (size_t ic=0; ic<tmp.col(); ++ic) {
            // fprintf(stderr, "r+ir: %zu\n", r+ir);
            if (c+ic < res[r+ir].size()) {
              res[r+ir][c+ic] = tmp[ir][ic];
            } else {
              res.add_col(r+ir, tmp[ir][ic]);
            }
          }
        }
        // fprintf(stderr, "> s[%zu]\n", i);
        if (s[i] == ' ') {
          c += tmp.col();
          ++i;
        } else if (s[i] == ';') {
          r = res.row();
          c = 0;
          ++i;
        } else {
          assert(s[i] == ']');
        }
      }
      ++i;
    } else {
      assert(false);
    }

    while (s[i] == '\'' || s[i] == '(') {
      char ch=s[i++];
      if (ch == '\'') {
        res = ~res;
      } else /* if (ch == '(') */ {
        const std::vector<int> fst=parse(s, i, vars, 0)[0];
        assert(s[i] == ',');
        const std::vector<int> snd=parse(s, ++i, vars, 0)[0];
        assert(s[i] == ')');
        ++i;
        res = res[std::make_pair(fst, snd)];
      }
    }
    // fprintf(stderr, ">> s[%zu]\n", i);
    return res;
  }

  Matrix lhs=parse(s, i, vars, preced+1);
  while (i < s.length()) {
    char op=s[i];
    if (!std::count(ops[preced].begin(), ops[preced].end(), op)) break;
    Matrix rhs=parse(s, ++i, vars, preced+1);
    if (op == '+') {
      lhs += rhs;
    } else if (op == '-') {
      lhs -= rhs;
    } else if (op == '*') {
      lhs *= rhs;
    }
  }
  return lhs;
}

int testcase_ends() {
  int n;
  scanf("%d", &n);
  if (n == 0) return 1;

  std::map<char, Matrix> vars;
  for (int i=0; i<n; ++i) {
    char buf[128];
    scanf(" %[^\n]", buf);
    std::string s=buf;
    fprintf(stderr, "%s\n", s.c_str());
    s.pop_back();
    char lhs=s[0];
    size_t j=2;
    Matrix rhs=parse(s, j, vars);
    //assert(s[j] == '.');
    rhs.output();
    vars[lhs] = rhs;
  }
  printf("-----\n");
  return 0;
}

int main() {
  while (!testcase_ends()) {}
}
accuracy: 1
time_ms: 10
memory_kb: 2900
final_rank: 1