int main(int argc, char** argv) {
  SatProblem cnf;
  cnf.parse(stdin);

  size_t count = 0;

  while (count < 100) {
    cerr << "count = " << count << endl;

    equivalences.clear();
    implications.clear();
    for (size_t i = 0; i < cnf.clauses.size(); ++i) {
      if (cnf.clauses[i].size() == 0) {
        abort();
      } else if (cnf.clauses[i].size() == 1) {
        addEquivalence(cnf.clauses[i][0], TRUE);
        addEquivalence(invert(cnf.clauses[i][0]), FALSE);
      } else if (cnf.clauses[i].size() == 2) {
        implications[invert(cnf.clauses[i][0])].push_back(cnf.clauses[i][1]);
        implications[invert(cnf.clauses[i][1])].push_back(cnf.clauses[i][0]);
      } else {
        // Do nothing
      }
    }

    done.clear();
    for (hash_map<Lit, vector<Lit> >::const_iterator i = implications.begin();
         i != implications.end(); ++i) {
      vector<Lit> stack;
      // cerr << "Exploring " << i->first << endl;
      explore(i->first, stack);
    }

    vector<Clause> oldClauses = cnf.clauses;
    cnf.clauses.clear();

    for (size_t i = 0; i < oldClauses.size(); ++i) {
      Clause cl = oldClauses[i];
      for (size_t j = 0; j < cl.size(); ++j) {
        cl[j] = normalize(cl[j]);
      }
      cnf.addClause(cl);
    }

    for (size_t i = 0; i < cnf.interfaceVariables.size(); ++i) {
      InterfaceVariable& iv = cnf.interfaceVariables[i];
      for (size_t j = 0; j < iv.second.size(); ++j) {
        Lit oldLit = iv.second[j];
        Lit newLit = normalize(oldLit);
        iv.second[j] = newLit;
      }
    }

    if (equivalences.empty()) break; // No changes

    ++count;
  }

  cnf.unparse(stdout);

  return 0;
}