AOJ 1314 - Matrix Calculator
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1314
概要
n 個の与えられた行列に関する代入式を評価した結果を出力する.
制約
- 1 <= n <= 10
- 入力は構文的に正しい
- 入力は意味的に正しい.つまり行列のサイズが合わない,インデックスが範囲外,未定義の変数の参照等は発生しない
- 評価中に表れる行列のサイズは 100x100 以下
解法
がんばって実装するだけ.
matrix が単に数字のみからなっていれば楽だが,問題文中の例にある
[[1 2 3;4 5 6] [7 8;9 10] [11;12];13 14 15 16 17 18]
のように,row の要素として任意の expr をとることができ,それを適切に展開しなければならない.
自分はまずすべての値を行列で表現し,row を vector<matrix>
で受け取り,row-seq を一旦 vector<vector<matrix> >
で受け取った後,
最終的な行列のサイズを計算してから展開するようにした.
aoj/1314.cc1 #include <iostream> 2 #include <vector> 3 #include <map> 4 #include <cassert> 5 using namespace std; 6 7 struct mod 8 { 9 int operator()(int n) const 10 { 11 static const int m = 32768; 12 return (n%m+m)%m; 13 } 14 }; 15 static const mod M = mod(); 16 17 struct matrix 18 { 19 vector<vector<int> > v; 20 matrix() {} 21 matrix(int r, int c) : v(r, vector<int>(c, 0)) {} 22 23 int row() const { return v.size(); } 24 int column() const { return v[0].size(); } 25 bool scalar() const { return row() == 1 && column() == 1; } 26 matrix transpose() const 27 { 28 matrix m(column(), row()); 29 for (int i = 0; i < row(); i++) { 30 for (int j = 0; j < column(); j++) { 31 m.v[j][i] = v[i][j]; 32 } 33 } 34 return m; 35 } 36 matrix& operator+=(const matrix& m) 37 { 38 assert(row() == m.row() && column() == m.column()); 39 for (int i = 0; i < row(); i++) { 40 for (int j = 0; j < column(); j++) { 41 v[i][j] = M(v[i][j] + m.v[i][j]); 42 } 43 } 44 return *this; 45 } 46 matrix& operator-=(const matrix& m) 47 { 48 assert(row() == m.row() && column() == m.column()); 49 for (int i = 0; i < row(); i++) { 50 for (int j = 0; j < column(); j++) { 51 v[i][j] = M(v[i][j] - m.v[i][j]); 52 } 53 } 54 return *this; 55 } 56 matrix& negate() 57 { 58 for (int i = 0; i < row(); i++) { 59 for (int j = 0; j < column(); j++) { 60 v[i][j] = M(-v[i][j]); 61 } 62 } 63 return *this; 64 } 65 }; 66 67 matrix operator*(const matrix& m1, const matrix& m2) 68 { 69 if (m1.scalar()) { 70 const int c = m1.v[0][0]; 71 matrix m(m2); 72 for (int i = 0; i < m2.row(); i++) { 73 for (int j = 0; j < m2.column(); j++) { 74 m.v[i][j] = M(m.v[i][j] * c); 75 } 76 } 77 return m; 78 } else if (m2.scalar()) { 79 return m2 * m1; 80 } else { 81 assert(m1.column() == m2.row()); 82 matrix m(m1.row(), m2.column()); 83 for (int i = 0; i < m1.row(); i++) { 84 for (int j = 0; j < m2.column(); j++) { 85 for (int k = 0; k < m1.column(); k++) { 86 m.v[i][j] = M(m.v[i][j] + m1.v[i][k]*m2.v[k][j]); 87 } 88 } 89 } 90 return m; 91 } 92 } 93 94 ostream& operator<<(ostream& os, const matrix& m) 95 { 96 for (int i = 0; i < m.row(); i++) { 97 for (int j = 0; j < m.column(); j++) { 98 if (j != 0) { 99 os << ' '; 100 } 101 os << m.v[i][j]; 102 } 103 os << endl; 104 } 105 return os; 106 } 107 108 typedef string::const_iterator Iterator; 109 map<char, matrix> env; 110 111 matrix number(Iterator& it, const Iterator& last) 112 { 113 int n = 0; 114 while (it != last && isdigit(*it)) { 115 n = 10*n + *it-'0'; 116 ++it; 117 } 118 matrix m(1, 1); 119 m.v[0][0] = n; 120 return m; 121 } 122 123 matrix expr(Iterator& it, const Iterator& last); 124 125 vector<matrix> row(Iterator& it, const Iterator& last) 126 { 127 vector<matrix> v(1, expr(it, last)); 128 while (*it == ' ') { 129 ++it; 130 v.push_back(expr(it, last)); 131 } 132 return v; 133 } 134 135 matrix rowseq(Iterator& it, const Iterator& last) 136 { 137 vector<matrix> rr = row(it, last); 138 vector<vector<matrix> > v(1, rr); 139 int r = rr[0].row(); 140 int c = 0; 141 for (vector<matrix>::const_iterator jt = rr.begin(); jt != rr.end(); ++jt) { 142 c += jt->column(); 143 } 144 while (*it == ';') { 145 ++it; 146 rr = row(it, last); 147 r += rr[0].row(); 148 v.push_back(rr); 149 } 150 matrix m(r, c); 151 int i = 0; 152 for (vector<vector<matrix> >::const_iterator jt = v.begin(); jt != v.end(); ++jt) { 153 int j = 0; 154 for (vector<matrix>::const_iterator kt = jt->begin(); kt != jt->end(); ++kt) { 155 for (int k = 0; k < kt->row(); k++) { 156 for (int l = 0; l < kt->column(); l++) { 157 m.v[i+k][j+l] = kt->v[k][l]; 158 } 159 } 160 j += kt->column(); 161 } 162 i += jt->front().row(); 163 } 164 return m; 165 } 166 167 matrix primary(Iterator& it, const Iterator& last) 168 { 169 matrix m; 170 if (*it == '[') { 171 ++it; 172 m = rowseq(it, last); 173 assert(*it == ']'); 174 ++it; 175 } else if (*it == '(') { 176 ++it; 177 m = expr(it, last); 178 assert(*it == ')'); 179 ++it; 180 } else if (isupper(*it)) { 181 const char var = *it; 182 ++it; 183 assert(env.count(var) != 0); 184 m = env[var]; 185 } else if (isdigit(*it)) { 186 m = number(it, last); 187 } else { 188 throw "primary parse error"; 189 } 190 191 while (it != last) { 192 if (*it == '(') { 193 // indexed-primary 194 ++it; 195 const matrix m1 = expr(it, last); 196 assert(m1.row() == 1); 197 assert(*it == ','); 198 ++it; 199 const matrix m2 = expr(it, last); 200 assert(m2.row() == 1); 201 assert(*it == ')'); 202 ++it; 203 matrix r(m1.column(), m2.column()); 204 for (int i = 0; i < m1.column(); i++) { 205 for (int j = 0; j < m2.column(); j++) { 206 r.v[i][j] = m.v[m1.v[0][i]-1][m2.v[0][j]-1]; 207 } 208 } 209 m = r; 210 } else if (*it == '\'') { 211 // transposed-primary 212 ++it; 213 m = m.transpose(); 214 } else { 215 break; 216 } 217 } 218 return m; 219 } 220 221 matrix factor(Iterator& it, const Iterator& last) 222 { 223 if (*it == '-') { 224 ++it; 225 return factor(it, last).negate(); 226 } else { 227 return primary(it, last); 228 } 229 } 230 231 matrix term(Iterator& it, const Iterator& last) 232 { 233 matrix m = factor(it, last); 234 while (it != last && *it == '*') { 235 ++it; 236 m = m * factor(it, last); 237 } 238 return m; 239 } 240 241 matrix expr(Iterator& it, const Iterator& last) 242 { 243 matrix m = term(it, last); 244 while (it != last && (*it == '+' || *it == '-')) { 245 const char op = *it; 246 ++it; 247 if (op == '+') { 248 m += term(it, last); 249 } else { 250 m -= term(it, last); 251 } 252 } 253 return m; 254 } 255 256 matrix assignment(Iterator& it, const Iterator& last) 257 { 258 assert(isupper(*it)); 259 const char var = *it; 260 ++it; 261 assert(*it == '='); 262 ++it; 263 const matrix m = expr(it, last); 264 assert(*it == '.'); 265 ++it; 266 assert(it == last); 267 return env[var] = m; 268 } 269 270 matrix eval(const string& s) 271 { 272 Iterator it = s.begin(), last = s.end(); 273 return assignment(it, last); 274 } 275 276 int main() 277 { 278 int N; 279 while (cin >> N && N != 0) { 280 env.clear(); 281 cin.ignore(); 282 for (int i = 0; i < N; i++) { 283 string s; 284 getline(cin, s); 285 const matrix m = eval(s); 286 cout << m; 287 } 288 cout << "-----" << endl; 289 } 290 return 0; 291 }