// misofov komentar:
// pouziva sa to:    ./i-tester 0/1 < jeho_vystup       (0 je easy, 1 je hard)
// potrebuje to v aktualnom adresari subory i*.in

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<sstream>
#include<vector>
#include<algorithm>
#include <fstream>

#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define SIZE(s) ((int)(s.size()))
#define SIZEP(x) (int)(sizeof(x)/sizeof(typeof(*(x))))

// instructions:
// AND a b   ~~~  a &= b
// NOT a     ~~~  a ~= a
// OR a b    ~~~  a |= b
// SHL a b   ~~~  (a << 1) b-times (b is a constant)
// SHR a b   ~~~  (a >> 1) b-times (b is a constant)
// MOV a b   ~~~  a := b
// GET a     ~~~  cin >> a
// PUT a     ~~~  cout << a

/// {{{ operations
#define AND  0
#define NOT  1
#define OR   2
#define SHL  3
#define SHR  4
#define MOV  5
#define GET  6
#define PUT  7
// }}}

#define TESTING 0
#define EASY 0
#define HARD 1
#define NO_REG 47 // indication that we do not have index to a register
// maximum number of commands
#define EASY_MAX_LEN_COMND 100  // if < 0, the length is not checked
#define HARD_MAX_LEN_COMND 300   // if < 0, the length is not checked
#define EASY_NUM_NOT 1
#define HARD_NUM_NOT 2 
#define EASY_NUM_GET 7
#define HARD_NUM_GET 19

// {{{ errors
#define EXIT_WRONG_CHARACTER 1   // wrong character in the input
#define EXIT_INSUFFICIENT_INPUT 2   // the input is unfinished
#define EXIT_INTERNAL 3   // our error
#define EXIT_TOO_LONG 4    // too long program 
#define EXIT_TOO_MANY_NOT 5 // too many operators not
#define EXIT_TOO_MANY_GET 6 // too many operators get
#define EXIT_WA 7         // wrong answer
#define EXIT_OK 0         // correct answer
// }}}

using namespace std;

string pwd_easy_in = "i1.in";
string pwd_hard_in = "i2.in";

int LEVEL;
unsigned char reg[26];  
string oper[10] = {"and","not","or","shl","shr","mov","get","put"};
vector<vector<unsigned char> > COMND; // sequence of commands: operator, to, from, constant

void fail(int error_code,string s) {
  if (TESTING) cerr << s << endl;
  exit(error_code);
}

// {{{ parsing input
void print_registers() {
  for(int i=0;i<26;++i) {
    cout << (char)(i+'a') << ":=";
    for(int j=7;j>=0;--j) cout << ((reg[i]&(1<<j))>0?1:0);
    if (i%12==11) cout << endl;
    else cout << " ";
  }
  cout << endl;
}

bool is_register(string s) {
  REP(i,26) if (s == string(1,i+'a')) return true;
  return false;
}

int get_register(string s) {
  REP(i,26) if (s == string(1,i+'a')) return i;
  return -1;
}

bool is_operator(string s) {
  REP(i,SIZEP(oper)) if (s == oper[i]) return true;
  return false;
}

bool get_constant(string s, unsigned char &K) {
  if (SIZE(s)==0) return false;  // empty string

  long long L=0;
  REP(i,SIZE(s)) {
    if (!isdigit(s[i])) return false;
    L*=10;
    L+=s[i]-'0';
    if (L >= (1LL<<8)) return false; // overflow
  }
  K = (unsigned char) L;
  return true;
}

//}}}

// {{{ reading input
// return 0 = line read, 1 = end of the input, 2 = error, 3 = empty line
int read_line(unsigned char &op, unsigned char &to, unsigned char &from, unsigned char &konst) {
  string s,line;
  vector<string> vstup;

  if (!getline(cin,line)) return 1;   // end of the input
  if (line=="") return 3;    // empty line
  op = from = to = NO_REG;

  stringstream SS(line);
  while(SS >> s) {
    REP(i,SIZE(s)) if (isalpha(s[i])) s[i] = tolower(s[i]);
    vstup.push_back(s);
    if (SIZE(vstup) >= 3) break;   // discarding the rest
  }

  if (SIZE(vstup) == 0) return 3;  // line of whitespaces

  // the first string must be an operator
  if (!is_operator(vstup[0])) {
    cout << "Syntax error (instruction expected, but '" << vstup[0] << "' found)" << endl;
    fail(EXIT_WRONG_CHARACTER,"prvy string ma byt operacia ale je \""+vstup[0]+"\"\n");
  }
  else REP(j,SIZEP(oper)) if (oper[j] == vstup[0]) { op=j; }

  // the check of the size of the input
  if (!(SIZE(vstup)==2 && (op==NOT || op==GET || op==PUT)) &&
      !(SIZE(vstup)==3 && (op==MOV || op==AND || op==OR || op==SHL || op==SHR))) {
    cout << "Syntax error (unexpected end of line)" << endl;
    fail(EXIT_INSUFFICIENT_INPUT,"Nedocitali sme korektny riadok\n");
  }

  // the check of the second string (always register)
  if (!is_register(vstup[1])) {
    cout << "Syntax error (register name expected, but '" << vstup[1] << "' found)" << endl;
    fail(EXIT_WRONG_CHARACTER,"druhy string ma byt register ale je \""+vstup[1]+"\"\n");
  }
  else {
    to = get_register(vstup[1]);
  }

  // we have read operand and register correctly and we can exit
  if (op == NOT || op == GET || op == PUT) return 0;

  // the check of the third string (register or a constant)

  if (op == SHL || op == SHR) { // the second parameter must be a contant
    if (!get_constant(vstup[2],konst)) {
      cout << "Syntax error (an 8-bit unsigned integer expected, but '" << vstup[2] << "' found)," << endl;
      fail(EXIT_WRONG_CHARACTER,"treti string nie je unsigned 8-bit konstanta, ale je \""+vstup[2]+"\"\n");
    }
  }
  else if (op == MOV || op == AND || op == OR) { //  -- the second parameter is either register or a constant
    if (is_register(vstup[2])) from = get_register(vstup[2]);
    else if (!get_constant(vstup[2],konst)) {
      cout << "Syntax error (register name or an 8-bit unsigned integer expected, but '" << vstup[2] << "' found)." << endl;
      fail(EXIT_WRONG_CHARACTER,"treti string nie je ani register a ani unsigned 8-bit konstantna, ale je \""+vstup[2]+"\"\n");
    }
  } 
  else {
    fail(EXIT_INTERNAL,"Sem sme sa nikdy nemali co dostat! Operand je \""+vstup[0]+"\"\n");
  }

  return 0;
}

void read_input() {
  unsigned char operand,from,to,konst;
  int cnt_not = 0;
  int cnt_get = 0;
  int cnt_put = 0;
  COMND.resize(0);
  while(1) {
    int result = read_line(operand, to, from, konst); // 0 succesfull line reading, 1 end of input, 3 empty line
    if (result == 1) break;
    if (result == 0) {
      vector<unsigned char> v(4);
      v[0] = operand;
      v[1] = to;
      v[2] = from;
      v[3] = konst;
      COMND.push_back(v);
      if (operand == NOT) ++cnt_not;
      if (operand == GET) ++cnt_get;
      if (operand == PUT) ++cnt_put;
    }
    if (result == 3) continue;
  }

  if (LEVEL == EASY && EASY_MAX_LEN_COMND >= 0 && SIZE(COMND) > EASY_MAX_LEN_COMND) {
    cout << "The code is too long." << endl;
    fail(EXIT_TOO_LONG,"Program je prilis dlhy\n");
  }
  if (LEVEL == HARD && HARD_MAX_LEN_COMND >= 0 && SIZE(COMND) > HARD_MAX_LEN_COMND) {
    cout << "The code is too long" << endl;
    fail(EXIT_TOO_LONG,"Program je prilis dlhy\n");
  }

  if ((LEVEL == EASY && cnt_not > EASY_NUM_NOT) || (LEVEL == HARD && cnt_not > HARD_NUM_NOT)) {
    cout << "Too many negations in your program." << endl;
    fail(EXIT_TOO_MANY_NOT,"Program obsahuje viac ako povoleny pocet negacii.\n");
  }

  if ((LEVEL == EASY && cnt_get > EASY_NUM_GET) || (LEVEL == HARD && cnt_get > HARD_NUM_GET)) {
    cout << "Cannot read the input, no more integers to read." << endl;
    fail(EXIT_TOO_MANY_GET,"Program pouziva prilis vela prikazov GET.\n");
  }

  if (cnt_get != cnt_put) {
    //cout << "Wrong answer.\n" << endl;
    fail(EXIT_WA,"Pocet nacitanych a vypisanych cisel je rozny.\n");
  }

}

// }}}

vector<unsigned char> interpret(unsigned long long W) {
  vector<unsigned char> ret(0);
  memset(reg,0,sizeof(reg));
  REP(i,SIZE(COMND)) {
    unsigned char operand = COMND[i][0];
    unsigned char to = COMND[i][1];
    unsigned char from = COMND[i][2];
    unsigned char konst = COMND[i][3];
    unsigned char value;
    if (from != NO_REG) value = reg[from];
    else value = konst;

    switch(operand) {
      case AND:  reg[to]&= value; break;
      case OR:   reg[to]|= value; break;
      case NOT:  reg[to] = ~reg[to]; break;
      case SHL:  if (value >= 8) reg[to] = 0;
                 else reg[to] = reg[to] << value; break;
      case SHR:  if (value >= 8) reg[to] = 0;
                 else reg[to] = reg[to] >> value; break;
      case MOV:  reg[to] = value; break;
      case GET:  reg[to] = (W%2); W/=2; break;
      case PUT:  ret.push_back(reg[to]); break;
    }
  }
  return ret;
}

// {{{ the body with execution of the code
int execution() {
  int ret=EXIT_OK;
  // the input, expecting binary number with last EASY_NUM_GET/HARD_NUM_GET least significant bits, the first is the least significat
  unsigned long long W;  
  ifstream F;

  if (LEVEL == EASY) {
    F.open(pwd_easy_in.c_str(),ios_base::in);
    if (!F.is_open()) fail(EXIT_INTERNAL,"Nepodarilo sa otvorit vstupny subor "+pwd_easy_in+"\n");
  }
  else {
    F.open(pwd_hard_in.c_str(),ios_base::in);
    if (!F.is_open()) fail(EXIT_INTERNAL,"Nepodarilo sa otvorit vstupny subor "+pwd_hard_in+"\n");
  }

  while(F >> W) {
    if (LEVEL == EASY && W >= (1ULL<<EASY_NUM_GET)) fail(EXIT_INTERNAL,"Nespravny format vstupneho cisla.\n");
    if (LEVEL == HARD && W >= (1ULL<<HARD_NUM_GET)) fail(EXIT_INTERNAL,"Nespravny format vstupneho cisla.\n");

    vector<unsigned char> output = interpret(W);

    int iter=0;
    if (LEVEL == EASY) iter = EASY_NUM_GET;
    else iter = HARD_NUM_GET;

    vector<unsigned char> answer;
    while(iter>0) {
      answer.push_back(1-(W%2));
      W/=2;
      --iter;
    }

    if (answer != output) {
      ret = EXIT_WA;
      break;
    }
  }
  if (ret == EXIT_WA); // cout << "Wrong answer" << endl;
  else cout << "OK" << endl;
  
  F.close();
  if (F.is_open()) fail(EXIT_INTERNAL,"Nepodarilo sa uzavriet subor "+pwd_easy_in+"\n");

  return ret;
}
// }}}

int main (int argc, char** argv) {
  if (argc != 2) fail(EXIT_INTERNAL,"Wrong number of parameters. The input should contain 0/1 = easy/hard test case.\n");
  LEVEL = atoi(argv[1]);
  if (LEVEL != EASY && LEVEL != HARD) fail(EXIT_INTERNAL,"Wrong number of parameters. The input is either 0 or 1 (easy/hard test case).\n");

  read_input();
  return execution();
}
  
