codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#include <unordered_map> #include <cstdio> #include <string> #include <vector> #include <cstring> #include <utility> using std::pair; using std::unordered_map; using std::string; using std::vector; const char code_path[20] = "sub_1.txt"; //code file const char grid_path[20] = "grid_1.txt"; //grid file const uint32_t gridN = 256; // grid size bool print_grid = true; //print final grid char code[1048571]; struct error { error() {} error(uint32_t a, uint32_t b, string c) : error_no(a), line(b), str(c) {} uint32_t error_no, line; string str; }; const uint32_t maxpeb = 15; uint8_t grid[gridN][gridN], grid_init[gridN][gridN]; uint32_t lines, tline; unordered_map<string, uint32_t> tag; //tag, line vector<pair<uint32_t, string>> totag; //line, tag vector<pair<uint32_t, uint32_t>> program; //mode, (toline) // 0: left, 1: right, 2: move, 3: get, 4: put, 5: halt, 6: jump, 7: border, 8: pebble void initialize() { freopen(grid_path, "r", stdin); memset(grid, 0x00, gridN * gridN); uint32_t x, y, t; while (~scanf("%u%u%u", &x, &y, &t)) { if (x >= gridN || x >= gridN || t > maxpeb) throw error(0, 0, ""); //invalid input grid[x][y] = t; } memcpy(grid_init, grid, gridN * gridN); lines = tline = 0; FILE* pFile = fopen(code_path, "r"); size_t p = fread(code, 1, 1048571, pFile); code[p] = 0; } inline bool isg(char p) { return (p >= 'A' && p <= 'Z' || p >= 'a' && p <= 'z' || p >= '0' && p <= '9' || p == '_'); } void compile_line(char* p, char* end) { tline++; string str[2]; bool flag = false; int8_t cr = 0; while (p != end) { if (isg(*p)) { if (cr == 2 || flag) throw error(1, tline, ""); //word after tag or two words str[cr] += *p; if (str[cr].size() > 128) throw error(2, tline, ""); //too long } else if (*p == ' ') { if (str[cr].size()) cr++; } else if (*p == '#' || *p == '\n' || *p == '\r' || *p == '\0') { if (str[cr].size()) cr++; break; } else if (*p == ':') { if (!str[cr].size()) throw error(3, tline, ""); //empty tag cr++, flag = true; } else throw error(4, tline, string(1, *p)); //invalid character p++; } if (flag) { if (tag.count(str[0])) throw error(5, tline, str[0]); //same-name tag tag[str[0]] = lines--; } else if (str[0] == "left" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(0, 0)); else if (str[0] == "right" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(1, 0)); else if (str[0] == "move" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(2, 0)); else if (str[0] == "get" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(3, 0)); else if (str[0] == "put" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(4, 0)); else if (str[0] == "halt" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(5, 0)); else if (str[0] == "jump" && str[1].size()) { program.push_back(pair<uint32_t, uint32_t>(6, 0)); totag.push_back(pair<uint32_t, string>(lines, str[1])); } else if (str[0] == "border" && str[1].size()) { program.push_back(pair<uint32_t, uint32_t>(7, 0)); totag.push_back(pair<uint32_t, string>(lines, str[1])); } else if (str[0] == "pebble" && str[1].size()) { program.push_back(pair<uint32_t, uint32_t>(8, 0)); totag.push_back(pair<uint32_t, string>(lines, str[1])); } else if (!str[0].size()) lines--; else throw error(6, tline, str[0] + ' ' + str[1]); //invalid command lines++; } void compile(char* p) { char *prev = p, *now = p; while (*now) { if (*now == '\n') { compile_line(prev, now + 1); prev = now + 1; } now++; } compile_line(prev, now + 1); unordered_map<string, uint32_t>::iterator it; for (auto& i : totag) { if ((it = tag.find(i.second)) != tag.end()) program[i.first].second = it->second; else throw error(7, 0, i.second); //undefined tag } } uint32_t tx, ty, dir; uint32_t nowline; uint32_t steps; const int32_t dy[4] = {0, -1, 0, 1}; //left++ const int32_t dx[4] = {-1, 0, 1, 0}; inline bool face_border() { return (!ty && dir == 1 || !tx && !dir || ty == gridN - 1 && dir == 3 || tx == gridN - 1 && dir == 2); } void execute() { nowline = steps = tx = ty = dir = 0; bool cont = true; while (cont && nowline < lines) { steps++; switch (program[nowline].first) { case 0: dir = (dir + 1) & 3; break; case 1: dir = (dir + 3) & 3; break; case 2: if (!face_border()) tx += dx[dir], ty += dy[dir]; break; case 3: if (grid[tx][ty]) grid[tx][ty]--; break; case 4: if (grid[tx][ty] != 15) grid[tx][ty]++; break; case 5: cont = false; break; case 6: nowline = program[nowline].second - 1; break; case 7: if (face_border()) nowline = program[nowline].second - 1; break; case 8: if (grid[tx][ty]) nowline = program[nowline].second - 1; } nowline++; } } int main() { try { initialize(); compile(code); printf("Compiled. Commands: %u.\n", lines); execute(); printf("Executed. Final position: (%u, %u). Steps: %u.\n", tx, ty, steps); if (print_grid) { for (uint32_t i = 0; i < gridN; i++) { for (uint32_t j = 0; j < gridN; j++) printf("%hhd ", grid[i][j]); putchar('\n'); } } } catch (error e) { puts("Complication error."); switch (e.error_no) { case 0: puts("Invalid grid input."); break; case 1: printf("Line %u: Text after tag or too many arguments.", e.line); break; case 2: printf("Line %u: Identifier is too long.", e.line); break; case 3: printf("Line %u: Empty tag.", e.line); break; case 4: printf("Line %u: Invalid character \'%s\'.", e.line, e.str.c_str()); break; case 5: printf("Line %u: Redefinition of tag \'%s\'.", e.line, e.str.c_str()); break; case 6: printf("Line %u: Invalid command \'%s\'.", e.line, e.str.c_str()); break; case 7: printf("Undefined tag \'%s\'.", e.str.c_str()); } } }
Private
[
?
]
Run code
Submit