QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#30952 | #3793. Killer Puzzle | Qingyu | AC ✓ | 5ms | 3780kb | C++23 | 17.5kb | 2022-05-02 12:26:08 | 2022-05-02 12:26:11 |
Judging History
answer
/*
* Task: Killer Puzzle
* Submitter: Qingyu Shi
* Submit Time: 2019.11.23 19:26:55
* Verdict: OK
*/
#include <cstdio>
#include <string>
#include <iostream>
#include <cstdint>
#include <vector>
#include <stack>
#include <cmath>
int32_t n, m;
typedef long double real_t;
namespace Debugger
{
inline void testInput();
}
namespace Solve
{
enum Type
{
integer,
string,
boolean,
function,
error
};
}
namespace IO
{
constexpr int SIZE = (1 << 16) - 1;
inline std::string getLine()
{
static char s[SIZE];
scanf(" %[^\n]s", s);
return std::string(s);
}
}
namespace Judger
{
inline bool endpos(const char c)
{
return c == '\0';
}
inline bool emptyChar(const char c)
{
return c == ' ' || c == '\r' || c == '\n' || c == '\0';
}
inline bool digitChar(const char c)
{
return c >= 48 && c <= 57;
}
inline bool checkConstant(const int32_t c)
{
return c == Solve::integer || c == Solve::string;
}
inline bool isPerfectSquare(const int32_t c)
{
if (c < 0) return false;
int32_t x = sqrtl(c);
return (x * x == c) || ((x + 1) * (x + 1) == c) || ((x - 1) * (x - 1) == c);
}
inline bool isPerfectCube(const int32_t c)
{
int32_t x = powl(c, 1.0L / 3);
return (x * x * x == c) || ((x + 1) * (x + 1) * (x + 1) == c) || ((x - 1) * (x - 1) * (x - 1) == c);
}
inline bool isPrime(const int32_t c)
{
if (c <= 1) return false;
if (c == 2) return true;
if (c % 2 == 0) return false;
for (int32_t i = 3; i * i <= c; i += 2)
{
if (c % i == 0)
{
return false;
}
}
return true;
}
inline bool isFactor(const int32_t c)
{
int64_t r = 1;
for (int32_t i = 1; ; ++i)
{
r *= i;
if (r == c) return true;
if (r > c) return false;
}
return false;
}
inline std::string to_lower(const std::string s)
{
std::string t = s;
int32_t length = s.length();
for (int i = 0; i < length; ++i) t[i] = tolower(s[i]);
return t;
}
inline bool isVowel(const std::string s)
{
std::string t = to_lower(s);
if (!isalpha(t[0])) return false;
return t.size() == 1 && ((t == "a") || (t == "e") || (t == "i") || (t == "o") || (t == "u"));
}
inline bool isConsonant(const std::string s)
{
if (!isalpha(s[0])) return false;
return s.size() == 1 && !isVowel(s);
}
inline bool isMultiple(int32_t x, int32_t y)
{
if (x == 0 && y == 0) return true;
if (y == 0) return false;
if (x % y == 0) return true;
return false;
}
}
namespace Solve
{
constexpr int COUNT = 12;
struct Data
{
Type data_type;
std::string data;
int32_t info;
Data(Type data_type, std::string data, int32_t info) : data_type(data_type), data(data), info(info)
{
}
} ERR(error, "", NULL), trueData(boolean, "", true), falseData(boolean, "", false);
struct Question
{
std::vector<Data> answers[6];
std::vector<int32_t> trans[6];
} Q[COUNT];
// Section A. Input
inline void loadData(std::vector<Data> &judge, std::vector<int32_t> &trans, std::string strInfo)
{
std::stack<int> expStack;
for (int i = 0; !Judger::endpos(strInfo[i]); ++i)
{
if (!Judger::emptyChar(strInfo[i]))
{
if (strInfo[i] == '\"') // Case 1: Typeof(datum) == string
{
std::string datum = "";
trans.push_back(-1);
++i;
while (strInfo[i] != '\"')
{
datum += strInfo[i++];
}
judge.push_back(Data(string, datum, NULL));
}
else if (Judger::digitChar(strInfo[i])) // Case 2: Typeof(datum) == int_t
{
int32_t datum = 0;
trans.push_back(-1);
while (Judger::digitChar(strInfo[i]))
{
datum = datum * 10 + strInfo[i++] - 48;
}
judge.push_back(Data(integer, "", datum));
--i;
}
else if (strInfo[i] == '(') // Case 3A
{
judge.push_back(Data(function, "(", NULL));
trans.push_back(-1);
expStack.push(trans.size() - 1);
}
else if (strInfo[i] == ')') // Case 3B
{
judge.push_back(Data(function, ")", NULL));
trans.push_back(-1);
trans[expStack.top()] = trans.size() - 1;
expStack.pop();
}
else // Case 4
{
std::string datum = "";
trans.push_back(-1);
while (!Judger::emptyChar(strInfo[i]) && strInfo[i] != '(' && strInfo[i] != ')')
{
datum += strInfo[i++];
}
--i;
judge.push_back(Data(function, datum, NULL));
}
}
}
}
// Section B. Functions
Data invokePred(std::vector<Data> &, std::vector<int32_t> &, int32_t, int32_t, Data);
Data invokeFunction(std::vector<Data> &, std::vector<int32_t> &, int32_t, int32_t);
std::vector<Data> now_answer;
std::vector<int32_t> now_trans;
char answerList[16];
Data invokePred(std::vector<Data> &answers, std::vector<int32_t> &trans, int32_t L, int32_t R, Data pred)
{
std::vector<std::pair<int32_t, int32_t> > arguments;
arguments.clear();
// Skip all '(' && ')'
while (trans[L] == R)
{
++L; --R;
}
if (L == R && Judger::checkConstant(answers[L].data_type))
{
return answers[L];
}
// Get arguments
int32_t oldL = L++;
while (L <= R)
{
int32_t last = L;
if (trans[L] != -1) last = trans[L];
arguments.push_back(std::make_pair(L, last));
L = last + 1;
}
L = oldL;
// Calculating the functions.
std::string funcName = answers[L].data;
// PartA: Pure pred.
if (funcName == "prime-p")
{
if (pred.data_type != integer) return ERR;
return Data(boolean, "", Judger::isPrime(pred.info));
}
else if (funcName == "factorial-p")
{
if (pred.data_type != integer) return ERR;
return Data(boolean, "", Judger::isFactor(pred.info));
}
else if (funcName == "square-p")
{
if (pred.data_type != integer) return ERR;
return Data(boolean, "", Judger::isPerfectSquare(pred.info));
}
else if (funcName == "cubic-p")
{
if (pred.data_type != integer) return ERR;
return Data(boolean, "", Judger::isPerfectCube(pred.info));
}
else if (funcName == "vowel-p")
{
if (pred.data_type != string) return ERR;
return Data(boolean, "", Judger::isVowel(pred.data));
}
else if (funcName == "consonant-p")
{
if (pred.data_type != string) return ERR;
return Data(boolean, "", Judger::isConsonant(pred.data));
}
// Part B: opt.
else if (funcName == "option-value")
{
return invokePred(now_answer, now_trans, 0, now_answer.size() - 1, pred);
}
// Part C: pred maker.
else if (funcName == "make-answer-diff-next-equal")
{
if (pred.data_type != integer) return ERR;
if (pred.info <= 0 || pred.info >= n) return ERR; // 1 <= pred_info, pred_info + 1 <= N => 0 < pred_info < N
Data __arg = invokeFunction(answers, trans, arguments[0].first, arguments[0].second);
if (__arg.data_type != integer) return ERR;
int32_t __distance = abs(answerList[pred.info] - answerList[pred.info + 1]);
return Data(boolean, "", __distance == __arg.info);
}
else if (funcName == "make-answer-equal")
{
if (pred.data_type != integer) return ERR; // (answer idx) will throw an exception.
if (pred.info <= 0 || pred.info > n) return ERR;
Data __arg = invokeFunction(answers, trans, arguments[0].first, arguments[0].second);
return Data(boolean, "", __arg.data.size() == 1 && __arg.data[0] == answerList[pred.info]);
}
else if (funcName == "make-answer-is")
{
if (pred.data_type != integer) return ERR; // (answer idx) will throw an exception.
if (pred.info <= 0 || pred.info > n) return ERR;
std::string transformed = ""; transformed += answerList[pred.info];
Data __arg = invokePred(answers, trans, arguments[0].first, arguments[0].second,
Data(string, transformed, NULL));
return Data(boolean, "", __arg.data_type == boolean && __arg.info == true);
}
else if (funcName == "make-answer-value-equal")
{
if (pred.data_type != integer) return ERR; // (answer-value idx) will throw an exception.
if (pred.info <= 0 || pred.info > n) return ERR;
std::vector<Data> &temp_answer = Q[pred.info].answers[answerList[pred.info] - 'a' + 1];
std::vector<int32_t> &temp_trans = Q[pred.info].trans[answerList[pred.info] - 'a' + 1];
Data __arg = invokeFunction(answers, trans, arguments[0].first, arguments[0].second),
__val = invokeFunction(temp_answer, temp_trans, 0, temp_answer.size() - 1);
return Data(boolean, "", __arg.data_type == __val.data_type
&& __arg.info == __val.info
&& __arg.data == __val.data);
}
else if (funcName == "make-answer-value-is")
{
if (pred.data_type != integer) return ERR;
if (pred.info <= 0 || pred.info > n) return ERR;
std::vector<Data> &temp_answer = Q[pred.info].answers[answerList[pred.info] - 'a' + 1];
std::vector<int32_t> &temp_trans = Q[pred.info].trans[answerList[pred.info] - 'a' + 1];
Data __val = invokeFunction(temp_answer, temp_trans, 0, temp_answer.size() - 1);
Data result = invokePred(answers, trans, arguments[0].first, arguments[0].second, __val);
return Data(boolean, "", result.data_type == boolean && result.info == true);
}
else if (funcName == "make-is-multiple")
{
if (pred.data_type != integer) return ERR;
Data result = invokeFunction(answers, trans, arguments[0].first, arguments[0].second);
if (result.data_type != integer)return ERR;
return Data(boolean, "", Judger::isMultiple(pred.info, result.info));
}
else if (funcName == "make-equal")
{
Data result = invokeFunction(answers, trans, arguments[0].first, arguments[0].second);
if (result.data_type != integer && result.data_type != string) return ERR;
return Data(boolean, "", result.data_type == pred.data_type
&& result.info == pred.info
&& result.data == pred.data);
}
else if (funcName == "make-not")
{
Data result = invokePred(answers, trans, arguments[0].first, arguments[0].second, pred);
if (result.data_type == boolean && !result.info)
{
return trueData;
}
else
{
return falseData;
}
}
else if (funcName == "make-and")
{
Data result1 = invokePred(answers, trans, arguments[0].first, arguments[0].second, pred);
if (result1.data_type != boolean || result1.info != true)
{
return falseData;
}
Data result2 = invokePred(answers, trans, arguments[1].first, arguments[1].second, pred);
if (result2.data_type != boolean || result2.info != true)
{
return falseData;
}
else
{
return trueData;
}
}
else if (funcName == "make-or")
{
Data result1 = invokePred(answers, trans, arguments[0].first, arguments[0].second, pred);
if (result1.data_type != boolean) return falseData;
Data result2 = invokePred(answers, trans, arguments[1].first, arguments[1].second, pred);
if (result1.data_type == boolean && result2.data_type == boolean && (result1.info == true || result2.info == true))
{
return trueData;
}
else
{
return falseData;
}
}
return ERR;
}
Data invokeFunction(std::vector<Data> &answers, std::vector<int32_t> &trans, int32_t L, int32_t R)
{
std::vector<std::pair<int32_t, int32_t> > arguments;
arguments.clear();
// Skip all paied "(" and ")"
while (trans[L] == R)
{
++L;
--R;
}
if (L == R && (answers[L].data_type == integer || answers[L].data_type == string))
{
return answers[L];
}
if (answers[L].data_type == function && answers[L].data == "(")
{
// answers[L] is actually just a pred.
int32_t argumentLeft = trans[L] + 1, argumentRight = argumentLeft;
if (trans[argumentRight] != -1)
{
argumentRight = trans[argumentRight];
}
Data pred = invokeFunction(answers, trans, argumentLeft, argumentRight);
return invokePred(answers, trans, L + 1, trans[L] - 1, pred);
}
// Get arguments.
int32_t oldL = L++;
while (L <= R)
{
int32_t last = L;
if (trans[last] != -1) last = trans[last];
arguments.push_back(std::make_pair(L, last));
L = last + 1;
}
L = oldL;
std::string funcName = answers[L].data;
if (funcName == "answer")
{
Data __arg = invokeFunction(answers, trans, arguments[0].first, arguments[0].second);
if (__arg.data_type != integer) return ERR;
if (__arg.info <= 0 || __arg.info > n) return ERR;
std::string transformed = ""; transformed += answerList[__arg.info];
return Data(string, transformed, NULL);
}
else if (funcName == "option-value")
{
return invokeFunction(now_answer, now_trans, 0, now_answer.size() - 1);
}
else if (funcName == "equal")
{
Data result1 = invokeFunction(answers, trans, arguments[0].first, arguments[0].second),
result2 = invokeFunction(answers, trans, arguments[1].first, arguments[1].second);
if (result1.data_type == error || result2.data_type == error) return ERR;
return Data(boolean, "", result1.data_type == result2.data_type
&& result1.info == result2.info
&& result1.data == result2.data);
}
else if (funcName == "answer-value")
{
Data __arg = invokeFunction(answers, trans, arguments[0].first, arguments[0].second);
if (__arg.data_type != integer) return ERR;
if (__arg.info <= 0 || __arg.info > n) return ERR;
std::vector<Data> &temp_answer = Q[__arg.info].answers[answerList[__arg.info] - 'a' + 1];
std::vector<int32_t> &temp_trans = Q[__arg.info].trans[answerList[__arg.info] - 'a' + 1];
return invokeFunction(temp_answer, temp_trans, 0, temp_answer.size() - 1);
}
else if (funcName == "first-question")
{
for (int32_t i = 1; i <= n; ++i)
{
Data result = invokePred(answers, trans, arguments[0].first, arguments[0].second, Data(integer, "", i));
if (result.data_type == boolean && result.info == true)
{
return Data(integer, "", i);
}
}
return ERR;
}
else if (funcName == "last-question")
{
for (int32_t i = n; i >= 1; --i)
{
Data result = invokePred(answers, trans, arguments[0].first, arguments[0].second, Data(integer, "", i));
if (result.data_type == boolean && result.info == true)
{
return Data(integer, "", i);
}
}
return ERR;
}
else if (funcName == "only-question")
{
int32_t solution = 0;
for (int32_t i = 1; i <= n; ++i)
{
Data result = invokePred(answers, trans, arguments[0].first, arguments[0].second, Data(integer, "", i));
if (result.data_type == boolean && result.info == true)
{
if (solution != 0)
{
return ERR;
}
else
{
solution = i;
}
}
}
if (solution != 0)
{
return Data(integer, "", solution);
}
return ERR;
}
else if (funcName == "count-question")
{
int32_t count = 0;
for (int32_t i = 1; i <= n; ++i)
{
Data result = invokePred(answers, trans, arguments[0].first, arguments[0].second, Data(integer, "", i));
if (result.data_type == boolean && result.info == true)
{
++count;
}
}
return Data(integer, "", count);
}
else if (funcName == "diff-answer")
{
Data result1 = invokeFunction(answers, trans, arguments[0].first, arguments[0].second);
if (result1.info <= 0 || result1.info > n || result1.data_type != integer)
{
return ERR;
}
Data result2 = invokeFunction(answers, trans, arguments[1].first, arguments[1].second);
if (result2.info <= 0 || result2.info > n || result2.data_type != integer)
{
return ERR;
}
return Data(integer, "", abs(answerList[result1.info] - answerList[result2.info]));
}
return ERR;
}
inline void Init()
{
for (int32_t i = 1; i <= n; ++i)
{
// Clear
for (int32_t j = 0; j <= m; ++j) Q[i].answers[j].clear(), Q[i].trans[j].clear();
// Read
for (int32_t j = 0; j <= m; ++j)
{
std::string strInfo = IO::getLine();
loadData(Q[i].answers[j], Q[i].trans[j], strInfo + " ");
}
}
// Debugger::testInput();
}
inline bool judge_option(Data __result)
{
return __result.data_type == boolean && __result.info == true;
}
inline void writeAnswer(const char *s)
{
printf("%s\n", s);
}
inline void checkAnswer(const char *s)
{
for (int32_t i = 1; i <= n; ++i)
{
for (int32_t j = 1; j <= m; ++j)
{
now_answer = Q[i].answers[j];
now_trans = Q[i].trans[j];
// Case 1: This option is "none-of-above"
if (j != m || Q[i].answers[j].size() > 1 || Q[i].answers[j][0].data != "none-of-above")
{
// Case 2: This option has been selected, so it must be correct.
if (j - 1 == s[i] - 'a' &&
!judge_option(invokeFunction(Q[i].answers[0], Q[i].trans[0], 0, Q[i].answers[0].size() - 1)))
{
return;
}
// Case 3: This option must be incorrect.
if (j - 1 != s[i] - 'a' &&
judge_option(invokeFunction(Q[i].answers[0], Q[i].trans[0], 0, Q[i].answers[0].size() - 1)))
{
return;
}
}
}
}
writeAnswer(s + 1);
}
void DFS(int32_t x)
{
if (x == n + 1)
{
answerList[n + 1] = '\0';
checkAnswer(answerList);
}
else
{
for (int32_t i = 0; i < m; ++i)
{
answerList[x] = i + 'a';
DFS(x + 1);
}
}
}
}
namespace Debugger
{
inline void testInput()
{
for (int32_t i = 1; i <= n; ++i)
{
for (int32_t j = 0; j <= m; ++j)
{
for (auto v : Solve::Q[i].answers[j]) printf("[%s, %d] ", v.data.c_str(), v.info);
putchar('\n');
for (auto v : Solve::Q[i].trans[j]) printf("%d ", v);
putchar('\n');
}
putchar('\n');
}
}
}
int main()
{
int32_t Case = 0;
while (scanf("%d%d", &n, &m) != EOF)
{
printf("Case %d:\n", ++Case);
Solve::Init();
Solve::DFS(1);
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 5ms
memory: 3780kb
input:
3 3 (equal (option-value) (count-question (make-answer-equal "a"))) 3 0 1 (equal (option-value) "a") "c" "b" "a" ((option-value) (count-question (make-answer-equal "c"))) (make-and (make-is-multiple 2) (make-or factorial-p prime-p)) (make-not prime-p) "none-of-above" 3 2 (equal (option-value) (an...
output:
Case 1: bcb cca Case 2: aab Case 3: aba Case 4: ab ee Case 5: abaa Case 6: bba Case 7: babbab Case 8: bbb Case 9: aba Case 10: cab Case 11: bba Case 12: caaac ccaac Case 13: bba Case 14: abbab Case 15: bac Case 16: abb Case 17: abbac Case 18: baab Case 19: accb Case 20: bba Case 21: aab Case 22: bba...
result:
ok 79 lines