// Verificador de "Turnos sin conflicto": verificador ENTRADA ESPERADA SALIDA.
// En ESPERADA está solo SI o NO. Si es NO, la salida tiene que ser exactamente NO. Si es SI, se lee el
// horario y se revisa cada pedido: no se le cree a nadie.
// Termina con 0 si todo está bien, y con 1 y un mensaje si no.
#include <cstddef>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>

namespace {

[[noreturn]] void reject(const std::string& reason) {
    std::cout << reason << '\n';
    std::exit(1);
}

bool holds(const std::string& schedule, int condition) {
    const std::size_t s = static_cast<std::size_t>(condition < 0 ? -condition : condition) - 1;
    return condition > 0 ? schedule[s] == 'M' : schedule[s] == 'T';
}

}  // namespace

int main(int argc, char* argv[]) {
    if (argc != 4) reject("uso: verificador ENTRADA ESPERADA SALIDA");
    std::ifstream input(argv[1]);
    std::ifstream expected(argv[2]);
    std::ifstream output(argv[3]);

    std::size_t n = 0;
    std::size_t m = 0;
    input >> n >> m;

    std::string answer;
    expected >> answer;

    std::string word;
    if (!(output >> word)) reject("la salida está vacía");
    if (word != "SI" && word != "NO") reject("la primera palabra tiene que ser SI o NO");
    if (word != answer) reject("se esperaba " + answer + ", salió " + word);
    if (word == "NO") {
        if (output >> word) reject("sobra texto después de NO");
        return 0;
    }

    std::string schedule;
    if (!(output >> schedule)) reject("falta el horario");
    if (schedule.size() != n) reject("el horario tiene " + std::to_string(schedule.size()) + " letras");
    for (char c : schedule) {
        if (c != 'M' && c != 'T') reject("el horario solo puede tener M y T");
    }
    if (output >> word) reject("sobra texto después del horario");

    for (std::size_t i = 1; i <= m; i++) {
        char kind = 0;
        int p = 0;
        int q = 0;
        input >> kind >> p >> q;
        const bool a = holds(schedule, p);
        const bool b = holds(schedule, q);
        bool fine = false;
        if (kind == 'O') fine = a || b;
        else if (kind == 'N') fine = !(a && b);
        else if (kind == 'S') fine = !a || b;
        else if (kind == 'D') fine = a != b;
        else reject("clase de pedido desconocida en la entrada");
        if (!fine) reject("no se cumple el pedido " + std::to_string(i));
    }
    return 0;
}
