#include <algorithm>
#include <array>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace {

struct Clause {
    std::vector<int> lits;
};

struct Formula {
    int vars = 0;
    int declared_clauses = 0;
    std::vector<Clause> clauses;
};

struct Block {
    std::array<int, 4> groups{};
    bool seen[81]{};
    int count = 0;
};

struct Key4 {
    std::array<int, 4> v{};

    bool operator==(const Key4& other) const noexcept {
        return v == other.v;
    }
};

struct Key4Hash {
    std::size_t operator()(const Key4& k) const noexcept {
        std::uint64_t h = 1469598103934665603ull;
        for (int x : k.v) {
            h ^= static_cast<std::uint64_t>(x + 0x9e3779b9);
            h *= 1099511628211ull;
        }
        return static_cast<std::size_t>(h);
    }
};

static std::uint64_t pair_key(int a, int b) {
    if (a > b) std::swap(a, b);
    return (static_cast<std::uint64_t>(static_cast<unsigned int>(a)) << 32) |
           static_cast<unsigned int>(b);
}

static int mod3(int x) {
    x %= 3;
    if (x < 0) x += 3;
    return x;
}

static bool parse_dimacs(const char* path, Formula& f) {
    std::ifstream in(path);
    if (!in) return false;

    std::string line;
    while (std::getline(in, line)) {
        if (line.empty()) continue;
        char first = 0;
        for (char ch : line) {
            if (ch != ' ' && ch != '\t' && ch != '\r') {
                first = ch;
                break;
            }
        }
        if (first == 0 || first == 'c') continue;

        if (first == 'p') {
            char cnf[16] = {};
            if (std::sscanf(line.c_str(), "p %15s %d %d", cnf, &f.vars,
                            &f.declared_clauses) != 3) {
                return false;
            }
            continue;
        }

        Clause c;
        const char* p = line.c_str();
        char* end = nullptr;
        while (true) {
            long v = std::strtol(p, &end, 10);
            if (p == end) break;
            p = end;
            if (v == 0) break;
            if (v < INT32_MIN || v > INT32_MAX) return false;
            c.lits.push_back(static_cast<int>(v));
        }
        f.clauses.push_back(std::move(c));
    }

    return f.vars > 0 && f.declared_clauses >= 0 &&
           (f.declared_clauses == 0 ||
            static_cast<int>(f.clauses.size()) == f.declared_clauses);
}

static int encode_value_tuple(const std::array<int, 4>& vals) {
    return (((vals[0] * 3 + vals[1]) * 3 + vals[2]) * 3 + vals[3]);
}

static bool fit_equation(const Block& b, std::array<unsigned char, 4>& coeffs,
                         unsigned char& rhs) {
    for (int mask = 0; mask < 8; ++mask) {
        std::array<unsigned char, 4> c{};
        c[0] = 1;
        c[1] = static_cast<unsigned char>((mask & 1) ? 2 : 1);
        c[2] = static_cast<unsigned char>((mask & 2) ? 2 : 1);
        c[3] = static_cast<unsigned char>((mask & 4) ? 2 : 1);

        for (int target = 0; target < 3; ++target) {
            bool ok = true;
            for (int a = 0; a < 3 && ok; ++a) {
                for (int d = 0; d < 3 && ok; ++d) {
                    for (int e = 0; e < 3 && ok; ++e) {
                        for (int g = 0; g < 3; ++g) {
                            std::array<int, 4> vals{a, d, e, g};
                            int code = encode_value_tuple(vals);
                            int sum = (c[0] * a + c[1] * d + c[2] * e +
                                       c[3] * g) %
                                      3;
                            bool should_forbid = (sum != target);
                            if (b.seen[code] != should_forbid) {
                                ok = false;
                                break;
                            }
                        }
                    }
                }
            }
            if (ok) {
                coeffs = c;
                rhs = static_cast<unsigned char>(target);
                return true;
            }
        }
    }
    return false;
}

static bool solve_gf3(std::vector<std::vector<unsigned char>>& mat, int ncols,
                      std::vector<unsigned char>& solution) {
    const int rows = static_cast<int>(mat.size());
    int rank = 0;
    std::vector<int> pivot_col;
    pivot_col.reserve(std::min(rows, ncols));

    for (int col = 0; col < ncols && rank < rows; ++col) {
        int pivot = -1;
        for (int r = rank; r < rows; ++r) {
            if (mat[r][col] != 0) {
                pivot = r;
                break;
            }
        }
        if (pivot < 0) continue;

        if (pivot != rank) std::swap(mat[pivot], mat[rank]);

        if (mat[rank][col] == 2) {
            for (int j = col; j <= ncols; ++j) {
                if (mat[rank][j]) mat[rank][j] = 3 - mat[rank][j];
            }
        }

        for (int r = rank + 1; r < rows; ++r) {
            unsigned char factor = mat[r][col];
            if (!factor) continue;
            if (factor == 1) {
                for (int j = col; j <= ncols; ++j) {
                    int v = static_cast<int>(mat[r][j]) -
                            static_cast<int>(mat[rank][j]);
                    mat[r][j] = static_cast<unsigned char>(mod3(v));
                }
            } else {
                for (int j = col; j <= ncols; ++j) {
                    int v = static_cast<int>(mat[r][j]) -
                            2 * static_cast<int>(mat[rank][j]);
                    mat[r][j] = static_cast<unsigned char>(mod3(v));
                }
            }
        }

        pivot_col.push_back(col);
        ++rank;
    }

    for (int r = rank; r < rows; ++r) {
        bool any = false;
        for (int c = 0; c < ncols; ++c) {
            if (mat[r][c] != 0) {
                any = true;
                break;
            }
        }
        if (!any && mat[r][ncols] != 0) return false;
    }

    solution.assign(ncols, 0);
    for (int r = rank - 1; r >= 0; --r) {
        int col = pivot_col[r];
        int val = mat[r][ncols];
        for (int c = col + 1; c < ncols; ++c) {
            if (mat[r][c] && solution[c]) {
                val -= static_cast<int>(mat[r][c]) *
                       static_cast<int>(solution[c]);
            }
        }
        solution[col] = static_cast<unsigned char>(mod3(val));
    }
    return true;
}

static bool recover_and_solve(const Formula& f,
                              std::vector<unsigned char>& gf3_solution,
                              std::vector<std::array<int, 3>>& groups) {
    if (f.vars <= 0 || f.vars % 3 != 0) return false;

    std::unordered_set<std::uint64_t> binary_pairs;
    binary_pairs.reserve(static_cast<std::size_t>(f.vars) * 3);

    std::vector<std::array<int, 3>> candidates;
    candidates.reserve(static_cast<std::size_t>(f.vars / 3));

    int four_clause_count = 0;

    for (const Clause& cl : f.clauses) {
        if (cl.lits.size() == 2) {
            if (cl.lits[0] >= 0 || cl.lits[1] >= 0) return false;
            int a = -cl.lits[0], b = -cl.lits[1];
            if (a < 1 || a > f.vars || b < 1 || b > f.vars || a == b) {
                return false;
            }
            if (!binary_pairs.insert(pair_key(a, b)).second) return false;
        } else if (cl.lits.size() == 3) {
            std::array<int, 3> t{cl.lits[0], cl.lits[1], cl.lits[2]};
            if (t[0] <= 0 || t[1] <= 0 || t[2] <= 0) return false;
            std::sort(t.begin(), t.end());
            if (t[0] < 1 || t[2] > f.vars || t[0] == t[1] ||
                t[1] == t[2]) {
                return false;
            }
            candidates.push_back(t);
        } else if (cl.lits.size() == 4) {
            ++four_clause_count;
            for (int lit : cl.lits) {
                if (lit >= 0 || -lit < 1 || -lit > f.vars) return false;
            }
        } else {
            return false;
        }
    }

    const int n_groups = f.vars / 3;
    if (static_cast<int>(candidates.size()) != n_groups) return false;

    std::sort(candidates.begin(), candidates.end());
    if (std::adjacent_find(candidates.begin(), candidates.end()) !=
        candidates.end()) {
        return false;
    }

    groups.assign(candidates.begin(), candidates.end());
    std::vector<int> var_group(f.vars + 1, -1);
    std::vector<int> var_value(f.vars + 1, -1);
    for (int g = 0; g < n_groups; ++g) {
        for (int v = 0; v < 3; ++v) {
            int dimacs_var = groups[g][v];
            if (var_group[dimacs_var] != -1) return false;
            var_group[dimacs_var] = g;
            var_value[dimacs_var] = v;
        }
        if (!binary_pairs.count(pair_key(groups[g][0], groups[g][1])) ||
            !binary_pairs.count(pair_key(groups[g][0], groups[g][2])) ||
            !binary_pairs.count(pair_key(groups[g][1], groups[g][2]))) {
            return false;
        }
    }

    if (static_cast<int>(binary_pairs.size()) != 3 * n_groups) return false;
    for (int v = 1; v <= f.vars; ++v) {
        if (var_group[v] < 0 || var_value[v] < 0) return false;
    }
    if (four_clause_count % 54 != 0) return false;

    std::unordered_map<Key4, Block, Key4Hash> blocks;
    blocks.reserve(static_cast<std::size_t>(four_clause_count / 54 + 8));

    for (const Clause& cl : f.clauses) {
        if (cl.lits.size() != 4) continue;

        std::array<std::pair<int, int>, 4> entries{};
        for (int i = 0; i < 4; ++i) {
            int var = -cl.lits[i];
            entries[i] = {var_group[var], var_value[var]};
        }
        std::sort(entries.begin(), entries.end(),
                  [](const auto& a, const auto& b) {
                      return a.first < b.first;
                  });
        for (int i = 1; i < 4; ++i) {
            if (entries[i - 1].first == entries[i].first) return false;
        }

        Key4 key;
        std::array<int, 4> vals{};
        for (int i = 0; i < 4; ++i) {
            key.v[i] = entries[i].first;
            vals[i] = entries[i].second;
        }

        int code = encode_value_tuple(vals);
        Block& b = blocks[key];
        if (b.count == 0) b.groups = key.v;
        if (b.seen[code]) return false;
        b.seen[code] = true;
        ++b.count;
    }

    if (blocks.empty()) return false;

    std::vector<std::vector<unsigned char>> matrix;
    matrix.reserve(blocks.size());
    for (const auto& it : blocks) {
        const Block& b = it.second;
        if (b.count != 54) return false;

        std::array<unsigned char, 4> coeffs{};
        unsigned char rhs = 0;
        if (!fit_equation(b, coeffs, rhs)) return false;

        std::vector<unsigned char> row(static_cast<std::size_t>(n_groups + 1),
                                       0);
        for (int i = 0; i < 4; ++i) {
            row[b.groups[i]] = coeffs[i];
        }
        row[n_groups] = rhs;
        matrix.push_back(std::move(row));
    }

    return solve_gf3(matrix, n_groups, gf3_solution);
}

static bool check_model(const Formula& f,
                        const std::vector<std::array<int, 3>>& groups,
                        const std::vector<unsigned char>& gf3_solution,
                        std::vector<int>& signed_model) {
    if (static_cast<int>(groups.size()) != static_cast<int>(gf3_solution.size())) {
        return false;
    }

    std::vector<unsigned char> truth(f.vars + 1, 0);
    for (std::size_t g = 0; g < groups.size(); ++g) {
        int value = gf3_solution[g];
        if (value < 0 || value > 2) return false;
        for (int v = 0; v < 3; ++v) {
            int dimacs_var = groups[g][v];
            truth[dimacs_var] = (v == value) ? 1 : 0;
        }
    }

    signed_model.assign(f.vars + 1, 0);
    for (int v = 1; v <= f.vars; ++v) {
        signed_model[v] = truth[v] ? v : -v;
    }

    for (const Clause& cl : f.clauses) {
        bool sat = false;
        for (int lit : cl.lits) {
            int var = std::abs(lit);
            if (var < 1 || var > f.vars) return false;
            bool val = truth[var] != 0;
            if ((lit > 0 && val) || (lit < 0 && !val)) {
                sat = true;
                break;
            }
        }
        if (!sat) return false;
    }
    return true;
}

static void print_unknown() {
    std::puts("s UNKNOWN");
}

static void print_model(const std::vector<int>& model) {
    std::puts("s SATISFIABLE");
    const int per_line = 100;
    int on_line = 0;
    std::printf("v");
    for (std::size_t i = 1; i < model.size(); ++i) {
        if (on_line == per_line) {
            std::printf("\nv");
            on_line = 0;
        }
        std::printf(" %d", model[i]);
        ++on_line;
    }
    std::printf(" 0\n");
}

}  // namespace

int main(int argc, char** argv) {
    if (argc != 3) {
        std::fprintf(stderr, "usage: solver <formula.cnf> <out.pbp>\n");
        return 1;
    }

    Formula formula;
    if (!parse_dimacs(argv[1], formula)) {
        print_unknown();
        return 0;
    }

    std::vector<unsigned char> gf3_solution;
    std::vector<std::array<int, 3>> groups;
    if (!recover_and_solve(formula, gf3_solution, groups)) {
        print_unknown();
        return 0;
    }

    std::vector<int> model;
    if (!check_model(formula, groups, gf3_solution, model)) {
        print_unknown();
        return 0;
    }

    print_model(model);
    return 10;
}
