#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
//#define TESTING
#ifdef TESTING
#define TEST_ASSERT(maCond) do { if (!(maCond)) { printf("%d: %s\n", __LINE__, #maCond); exit(1); } } while (0)
#define TEST_ASSERT_MSG(maCond, maFormat, maMsg) \
do { \
if (!(maCond)) { printf("%d: %s: '" maFormat "'\n", __LINE__, #maCond, (maMsg)); exit(1); } \
} while (0)
#define IF_TESTING(...) __VA_ARGS__
#else
#define TEST_ASSERT(maCond) do {} while (0)
#define TEST_ASSERT_MSG(maCond, maFormat, maMsg) do {} while(0)
#define IF_TESTING(...)
#endif
//#define TRACING
#ifdef TRACING
#define TRACE(msg, ...) printf(msg "\n", __VA_ARGS__)
#else
#define TRACE(...) do {} while (0)
#endif
#define MAX_NODE_COUNT (255)
#define MAX_INPUT_SIZE (255)
enum ParsingContext
{
CONTEXT_FIRST_TERM
, CONTEXT_ADDITIVE_EXPRESSION
, CONTEXT_NONFIRST_TERM
};
struct ExprNode
{
char type;
struct ExprNode *child[2];
};
struct NodeMemory
{
struct ExprNode data[MAX_NODE_COUNT];
struct ExprNode *end;
};
struct ExprNode* createNode(struct NodeMemory *mem, char type)
{
struct ExprNode *node = mem->end++;
TEST_ASSERT(mem->end - mem->data <= MAX_NODE_COUNT);
node->type = type;
IF_TESTING(
node->child[0] = node->child[1] = NULL;
)
return node;
}
struct ExprNode* moveToChild(
struct NodeMemory * restrict mem
, struct ExprNode * restrict node
, size_t idxChild
, char newParentType
)
{
struct ExprNode * result = createNode(mem, newParentType);
result->child[idxChild] = node;
return result;
}
char readChar(const char * restrict * restrict in)
{
char c = **in;
++*in;
return c;
}
void writeChar(char * restrict * restrict out, char c)
{
**out = c;
++*out;
}
struct ExprNode* parse(
struct NodeMemory * restrict mem
, const char * restrict * restrict in
, struct ExprNode * restrict root
, enum ParsingContext context
)
{
TEST_ASSERT(root != NULL);
bool skipStart = (context == CONTEXT_NONFIRST_TERM);
// Left operand
if (!skipStart) {
switch (**in) {
case '(':
++*in;
root = parse(mem, in, root, CONTEXT_FIRST_TERM);
TEST_ASSERT_MSG(**in == ')', "%c", **in);
++*in;
break;
default:
TEST_ASSERT_MSG(
**in != ')'
&& **in != '+'
&& **in != '-'
&& **in != '*'
&& **in != '/'
&& **in != '\n'
, "%c", **in
);
root->type = readChar(in);
break;
}
}
for (;;) {
// Operator
if (!skipStart) {
switch (**in) {
case '\n':
case ')':
TEST_ASSERT(root != NULL);
TEST_ASSERT(root->type != '.');
return root;
case '+':
case '-':
if (context == CONTEXT_NONFIRST_TERM) {
TEST_ASSERT(root != NULL);
TEST_ASSERT(root->type != '.');
return root;
}
TEST_ASSERT(
(context == CONTEXT_ADDITIVE_EXPRESSION)
==
(root->type == '+' || root->type == '-')
);
context = CONTEXT_ADDITIVE_EXPRESSION;
root = moveToChild(mem, root, 0, readChar(in));
break;
case '*':
case '/':
if (context == CONTEXT_ADDITIVE_EXPRESSION) {
TEST_ASSERT(root->child[1]->type != '.');
root->child[1] = moveToChild(mem, root->child[1], 0, readChar(in));
root->child[1] = parse(mem, in, root->child[1], CONTEXT_NONFIRST_TERM);
continue; // Parsed up to next operator or teminator
}
root = moveToChild(mem, root, 0, readChar(in));
break;
default:
TEST_ASSERT(false);
break;
}
}
skipStart = false;
// Right operand
switch (**in) {
case '(':
++*in;
root->child[1] = parse(mem, in, createNode(mem, '.'), CONTEXT_FIRST_TERM);
TEST_ASSERT_MSG(**in == ')', "%c", **in);
++*in;
break;
default:
TEST_ASSERT_MSG(
**in != ')'
&& **in != '+'
&& **in != '-'
&& **in != '*'
&& **in != '/'
&& **in != '\n'
, "%c", **in
);
root->child[1] = createNode(mem, readChar(in));
break;
}
}
}
void serialiseTree(const struct ExprNode * restrict node, char * restrict * restrict out, char parentType, bool isLeftChild)
{
IF_TESTING(
if (!node) {
writeChar(out, 'N');
return;
}
)
TEST_ASSERT(
parentType == '+'
|| parentType == '-'
|| parentType == '*'
|| parentType == '/'
);
bool paren = false;
switch (node->type) {
case '+':
case '-':
paren = (
parentType == '*'
|| parentType == '/'
|| (parentType == '-' && !isLeftChild)
);
break;
case '*':
case '/':
paren = (parentType == '/' && !isLeftChild);
break;
default:
writeChar(out, node->type);
return;
}
if (paren) {
writeChar(out, '(');
}
serialiseTree(node->child[0], out, node->type, true);
writeChar(out, node->type);
serialiseTree(node->child[1], out, node->type, false);
if (paren) {
writeChar(out, ')');
}
}
void createTree(struct NodeMemory *mem)
{
char expr[MAX_INPUT_SIZE + 2];
fgets(expr
, sizeof(expr
), stdin
); const char *in = expr;
if (*in == '\n') {
return;
}
struct ExprNode *root = parse(mem, &in, createNode(mem, '.'), CONTEXT_FIRST_TERM);
TEST_ASSERT(*in == '\n');
TEST_ASSERT(root != NULL);
char *out = expr;
serialiseTree(root, &out, '+', true);
*out++ = '\n';
*out = 0;
TEST_ASSERT(out - expr < sizeof(expr));
}
void runCase(void)
{
struct NodeMemory mem;
mem.end = mem.data;
createTree(&mem);
}
int main(void) {
int caseCount;
fscanf(stdin
, "%d\n", &caseCount
); for (int idxCase = 0; idxCase < caseCount; ++idxCase) {
runCase();
}
return 0;
}
I2luY2x1ZGUgPHN0ZGJvb2wuaD4KI2luY2x1ZGUgPHN0ZGRlZi5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgoKCi8vI2RlZmluZSBURVNUSU5HCgojaWZkZWYgVEVTVElORwoJI2RlZmluZSBURVNUX0FTU0VSVChtYUNvbmQpIGRvIHsgaWYgKCEobWFDb25kKSkgeyBwcmludGYoIiVkOiAlc1xuIiwgX19MSU5FX18sICNtYUNvbmQpOyBleGl0KDEpOyB9IH0gd2hpbGUgKDApCgkjZGVmaW5lIFRFU1RfQVNTRVJUX01TRyhtYUNvbmQsIG1hRm9ybWF0LCBtYU1zZykgXAoJCWRvIHsgXAoJCQlpZiAoIShtYUNvbmQpKSB7IHByaW50ZigiJWQ6ICVzOiAnIiBtYUZvcm1hdCAiJ1xuIiwgX19MSU5FX18sICNtYUNvbmQsIChtYU1zZykpOyBleGl0KDEpOyB9IFwKCQl9IHdoaWxlICgwKQoJI2RlZmluZSBJRl9URVNUSU5HKC4uLikgX19WQV9BUkdTX18KI2Vsc2UKCSNkZWZpbmUgVEVTVF9BU1NFUlQobWFDb25kKSBkbyB7fSB3aGlsZSAoMCkKCSNkZWZpbmUgVEVTVF9BU1NFUlRfTVNHKG1hQ29uZCwgbWFGb3JtYXQsIG1hTXNnKSBkbyB7fSB3aGlsZSgwKQoJI2RlZmluZSBJRl9URVNUSU5HKC4uLikKI2VuZGlmCgoKLy8jZGVmaW5lIFRSQUNJTkcKCiNpZmRlZiBUUkFDSU5HCgkjZGVmaW5lIFRSQUNFKG1zZywgLi4uKSBwcmludGYobXNnICJcbiIsIF9fVkFfQVJHU19fKQojZWxzZQoJI2RlZmluZSBUUkFDRSguLi4pIGRvIHt9IHdoaWxlICgwKQojZW5kaWYKCgojZGVmaW5lIE1BWF9OT0RFX0NPVU5UICgyNTUpCiNkZWZpbmUgTUFYX0lOUFVUX1NJWkUgKDI1NSkKCgplbnVtIFBhcnNpbmdDb250ZXh0CnsKCUNPTlRFWFRfRklSU1RfVEVSTQoJLCBDT05URVhUX0FERElUSVZFX0VYUFJFU1NJT04KCSwgQ09OVEVYVF9OT05GSVJTVF9URVJNCn07CgoKc3RydWN0IEV4cHJOb2RlCnsKCWNoYXIgdHlwZTsKCXN0cnVjdCBFeHByTm9kZSAqY2hpbGRbMl07Cn07CgoKc3RydWN0IE5vZGVNZW1vcnkKewoJc3RydWN0IEV4cHJOb2RlIGRhdGFbTUFYX05PREVfQ09VTlRdOwoJc3RydWN0IEV4cHJOb2RlICplbmQ7Cn07CgoKc3RydWN0IEV4cHJOb2RlKiBjcmVhdGVOb2RlKHN0cnVjdCBOb2RlTWVtb3J5ICptZW0sIGNoYXIgdHlwZSkKewoJc3RydWN0IEV4cHJOb2RlICpub2RlID0gbWVtLT5lbmQrKzsKCVRFU1RfQVNTRVJUKG1lbS0+ZW5kIC0gbWVtLT5kYXRhIDw9IE1BWF9OT0RFX0NPVU5UKTsKCW5vZGUtPnR5cGUgPSB0eXBlOwoJSUZfVEVTVElORygKCQlub2RlLT5jaGlsZFswXSA9IG5vZGUtPmNoaWxkWzFdID0gTlVMTDsKCSkKCXJldHVybiBub2RlOwp9CgoKc3RydWN0IEV4cHJOb2RlKiBtb3ZlVG9DaGlsZCgKCXN0cnVjdCBOb2RlTWVtb3J5ICogcmVzdHJpY3QgbWVtCgksIHN0cnVjdCBFeHByTm9kZSAqIHJlc3RyaWN0IG5vZGUKCSwgc2l6ZV90IGlkeENoaWxkCgksIGNoYXIgbmV3UGFyZW50VHlwZQopCnsKCXN0cnVjdCBFeHByTm9kZSAqIHJlc3VsdCA9IGNyZWF0ZU5vZGUobWVtLCBuZXdQYXJlbnRUeXBlKTsKCXJlc3VsdC0+Y2hpbGRbaWR4Q2hpbGRdID0gbm9kZTsKCXJldHVybiByZXN1bHQ7Cn0KCgpjaGFyIHJlYWRDaGFyKGNvbnN0IGNoYXIgKiByZXN0cmljdCAqIHJlc3RyaWN0IGluKQp7CgljaGFyIGMgPSAqKmluOwoJKysqaW47CglyZXR1cm4gYzsKfQoKCnZvaWQgd3JpdGVDaGFyKGNoYXIgKiByZXN0cmljdCAqIHJlc3RyaWN0IG91dCwgY2hhciBjKQp7CgkqKm91dCA9IGM7CgkrKypvdXQ7Cn0KCgpzdHJ1Y3QgRXhwck5vZGUqIHBhcnNlKAoJc3RydWN0IE5vZGVNZW1vcnkgKiByZXN0cmljdCBtZW0KCSwgY29uc3QgY2hhciAqIHJlc3RyaWN0ICogcmVzdHJpY3QgaW4KCSwgc3RydWN0IEV4cHJOb2RlICogcmVzdHJpY3Qgcm9vdAoJLCBlbnVtIFBhcnNpbmdDb250ZXh0IGNvbnRleHQKKQp7CglURVNUX0FTU0VSVChyb290ICE9IE5VTEwpOwoJYm9vbCBza2lwU3RhcnQgPSAoY29udGV4dCA9PSBDT05URVhUX05PTkZJUlNUX1RFUk0pOwoJLy8gTGVmdCBvcGVyYW5kCglpZiAoIXNraXBTdGFydCkgewoJCXN3aXRjaCAoKippbikgewoJCQljYXNlICcoJzoKCQkJCSsrKmluOwoJCQkJcm9vdCA9IHBhcnNlKG1lbSwgaW4sIHJvb3QsIENPTlRFWFRfRklSU1RfVEVSTSk7CgkJCQlURVNUX0FTU0VSVF9NU0coKippbiA9PSAnKScsICIlYyIsICoqaW4pOwoJCQkJKysqaW47CgkJCQlicmVhazsKCQkJZGVmYXVsdDoKCQkJCVRFU1RfQVNTRVJUX01TRygKCQkJCQkqKmluICE9ICcpJwoJCQkJCSYmICoqaW4gIT0gJysnCgkJCQkJJiYgKippbiAhPSAnLScKCQkJCQkmJiAqKmluICE9ICcqJwoJCQkJCSYmICoqaW4gIT0gJy8nCgkJCQkJJiYgKippbiAhPSAnXG4nCgkJCQkJLCAiJWMiLCAqKmluCgkJCQkpOwoJCQkJcm9vdC0+dHlwZSA9IHJlYWRDaGFyKGluKTsKCQkJCWJyZWFrOwoJCX0KCX0KCWZvciAoOzspIHsKCQkvLyBPcGVyYXRvcgoJCWlmICghc2tpcFN0YXJ0KSB7CgkJCXN3aXRjaCAoKippbikgewoJCQkJY2FzZSAnXG4nOgoJCQkJY2FzZSAnKSc6CgkJCQkJVEVTVF9BU1NFUlQocm9vdCAhPSBOVUxMKTsKCQkJCQlURVNUX0FTU0VSVChyb290LT50eXBlICE9ICcuJyk7CgkJCQkJcmV0dXJuIHJvb3Q7CgkJCQljYXNlICcrJzoKCQkJCWNhc2UgJy0nOgoJCQkJCWlmIChjb250ZXh0ID09IENPTlRFWFRfTk9ORklSU1RfVEVSTSkgewoJCQkJCQlURVNUX0FTU0VSVChyb290ICE9IE5VTEwpOwoJCQkJCQlURVNUX0FTU0VSVChyb290LT50eXBlICE9ICcuJyk7CgkJCQkJCXJldHVybiByb290OwoJCQkJCX0KCQkJCQlURVNUX0FTU0VSVCgKCQkJCQkJKGNvbnRleHQgPT0gQ09OVEVYVF9BRERJVElWRV9FWFBSRVNTSU9OKQoJCQkJCQk9PQoJCQkJCQkocm9vdC0+dHlwZSA9PSAnKycgfHwgcm9vdC0+dHlwZSA9PSAnLScpCgkJCQkJKTsKCQkJCQljb250ZXh0ID0gQ09OVEVYVF9BRERJVElWRV9FWFBSRVNTSU9OOwoJCQkJCXJvb3QgPSBtb3ZlVG9DaGlsZChtZW0sIHJvb3QsIDAsIHJlYWRDaGFyKGluKSk7CgkJCQkJYnJlYWs7CgkJCQljYXNlICcqJzoKCQkJCWNhc2UgJy8nOgoJCQkJCWlmIChjb250ZXh0ID09IENPTlRFWFRfQURESVRJVkVfRVhQUkVTU0lPTikgewoJCQkJCQlURVNUX0FTU0VSVChyb290LT5jaGlsZFsxXS0+dHlwZSAhPSAnLicpOwoJCQkJCQlyb290LT5jaGlsZFsxXSA9IG1vdmVUb0NoaWxkKG1lbSwgcm9vdC0+Y2hpbGRbMV0sIDAsIHJlYWRDaGFyKGluKSk7CgkJCQkJCXJvb3QtPmNoaWxkWzFdID0gcGFyc2UobWVtLCBpbiwgcm9vdC0+Y2hpbGRbMV0sIENPTlRFWFRfTk9ORklSU1RfVEVSTSk7CgkJCQkJCWNvbnRpbnVlOwkvLyBQYXJzZWQgdXAgdG8gbmV4dCBvcGVyYXRvciBvciB0ZW1pbmF0b3IKCQkJCQl9CgkJCQkJcm9vdCA9IG1vdmVUb0NoaWxkKG1lbSwgcm9vdCwgMCwgcmVhZENoYXIoaW4pKTsKCQkJCQlicmVhazsKCQkJCWRlZmF1bHQ6CgkJCQkJVEVTVF9BU1NFUlQoZmFsc2UpOwoJCQkJCWJyZWFrOwoJCQl9CgkJfQoJCXNraXBTdGFydCA9IGZhbHNlOwoJCS8vIFJpZ2h0IG9wZXJhbmQKCQlzd2l0Y2ggKCoqaW4pIHsKCQkJY2FzZSAnKCc6CgkJCQkrKyppbjsKCQkJCXJvb3QtPmNoaWxkWzFdID0gcGFyc2UobWVtLCBpbiwgY3JlYXRlTm9kZShtZW0sICcuJyksIENPTlRFWFRfRklSU1RfVEVSTSk7CgkJCQlURVNUX0FTU0VSVF9NU0coKippbiA9PSAnKScsICIlYyIsICoqaW4pOwoJCQkJKysqaW47CgkJCQlicmVhazsKCQkJZGVmYXVsdDoKCQkJCVRFU1RfQVNTRVJUX01TRygKCQkJCQkqKmluICE9ICcpJwoJCQkJCSYmICoqaW4gIT0gJysnCgkJCQkJJiYgKippbiAhPSAnLScKCQkJCQkmJiAqKmluICE9ICcqJwoJCQkJCSYmICoqaW4gIT0gJy8nCgkJCQkJJiYgKippbiAhPSAnXG4nCgkJCQkJLCAiJWMiLCAqKmluCgkJCQkpOwoJCQkJcm9vdC0+Y2hpbGRbMV0gPSBjcmVhdGVOb2RlKG1lbSwgcmVhZENoYXIoaW4pKTsKCQkJCWJyZWFrOwoJCX0KCX0KfQoKCgp2b2lkIHNlcmlhbGlzZVRyZWUoY29uc3Qgc3RydWN0IEV4cHJOb2RlICogcmVzdHJpY3Qgbm9kZSwgY2hhciAqIHJlc3RyaWN0ICogcmVzdHJpY3Qgb3V0LCBjaGFyIHBhcmVudFR5cGUsIGJvb2wgaXNMZWZ0Q2hpbGQpCnsKCUlGX1RFU1RJTkcoCgkJaWYgKCFub2RlKSB7CgkJCXdyaXRlQ2hhcihvdXQsICdOJyk7CgkJCXJldHVybjsKCQl9CgkpCglURVNUX0FTU0VSVCgKCQlwYXJlbnRUeXBlID09ICcrJwoJCXx8IHBhcmVudFR5cGUgPT0gJy0nCgkJfHwgcGFyZW50VHlwZSA9PSAnKicKCQl8fCBwYXJlbnRUeXBlID09ICcvJwoJKTsKCWJvb2wgcGFyZW4gPSBmYWxzZTsKCXN3aXRjaCAobm9kZS0+dHlwZSkgewoJCWNhc2UgJysnOgoJCWNhc2UgJy0nOgoJCQlwYXJlbiA9ICgKCQkJCXBhcmVudFR5cGUgPT0gJyonCgkJCQl8fCBwYXJlbnRUeXBlID09ICcvJwoJCQkJfHwgKHBhcmVudFR5cGUgPT0gJy0nICYmICFpc0xlZnRDaGlsZCkKCQkJKTsKCQkJYnJlYWs7CgkJY2FzZSAnKic6CgkJY2FzZSAnLyc6CgkJCXBhcmVuID0gKHBhcmVudFR5cGUgPT0gJy8nICYmICFpc0xlZnRDaGlsZCk7CgkJCWJyZWFrOwoJCWRlZmF1bHQ6CgkJCXdyaXRlQ2hhcihvdXQsIG5vZGUtPnR5cGUpOwoJCQlyZXR1cm47Cgl9CglpZiAocGFyZW4pIHsKCQl3cml0ZUNoYXIob3V0LCAnKCcpOwoJfQoJc2VyaWFsaXNlVHJlZShub2RlLT5jaGlsZFswXSwgb3V0LCBub2RlLT50eXBlLCB0cnVlKTsKCXdyaXRlQ2hhcihvdXQsIG5vZGUtPnR5cGUpOwoJc2VyaWFsaXNlVHJlZShub2RlLT5jaGlsZFsxXSwgb3V0LCBub2RlLT50eXBlLCBmYWxzZSk7CglpZiAocGFyZW4pIHsKCQl3cml0ZUNoYXIob3V0LCAnKScpOwoJfQp9CgoKCnZvaWQgY3JlYXRlVHJlZShzdHJ1Y3QgTm9kZU1lbW9yeSAqbWVtKQp7CgljaGFyIGV4cHJbTUFYX0lOUFVUX1NJWkUgKyAyXTsKCWZnZXRzKGV4cHIsIHNpemVvZihleHByKSwgc3RkaW4pOwoJY29uc3QgY2hhciAqaW4gPSBleHByOwoJaWYgKCppbiA9PSAnXG4nKSB7CgkJZnB1dHMoZXhwciwgc3Rkb3V0KTsKCQlyZXR1cm47Cgl9CglzdHJ1Y3QgRXhwck5vZGUgKnJvb3QgPSBwYXJzZShtZW0sICZpbiwgY3JlYXRlTm9kZShtZW0sICcuJyksIENPTlRFWFRfRklSU1RfVEVSTSk7CglURVNUX0FTU0VSVCgqaW4gPT0gJ1xuJyk7CglURVNUX0FTU0VSVChyb290ICE9IE5VTEwpOwoJY2hhciAqb3V0ID0gZXhwcjsKCXNlcmlhbGlzZVRyZWUocm9vdCwgJm91dCwgJysnLCB0cnVlKTsKCSpvdXQrKyA9ICdcbic7Cgkqb3V0ID0gMDsKCVRFU1RfQVNTRVJUKG91dCAtIGV4cHIgPCBzaXplb2YoZXhwcikpOwoJZnB1dHMoZXhwciwgc3Rkb3V0KTsKfQoKCgp2b2lkIHJ1bkNhc2Uodm9pZCkKewoJc3RydWN0IE5vZGVNZW1vcnkgbWVtOwoJbWVtLmVuZCA9IG1lbS5kYXRhOwoJY3JlYXRlVHJlZSgmbWVtKTsKfQoKCgppbnQgbWFpbih2b2lkKSB7CglpbnQgY2FzZUNvdW50OwoJZnNjYW5mKHN0ZGluLCAiJWRcbiIsICZjYXNlQ291bnQpOwoJZm9yIChpbnQgaWR4Q2FzZSA9IDA7IGlkeENhc2UgPCBjYXNlQ291bnQ7ICsraWR4Q2FzZSkgewoJCXJ1bkNhc2UoKTsKCX0KCXJldHVybiAwOwp9Cg==