P3695 CYaRon!语

Akano 发布于 2023-06-26 4 次阅读


P3695 CYaRon!语

P3695 CYaRon!语

思路

最喜欢的一集(指大模拟)

因为是大模拟所以其实没什么好讲的,就说一下写大模拟的细节吧。

首先因为大模拟一般时间复杂度都是不会卡的,所以说先写一堆不考虑复杂度的函数备用着(造轮子),比如说本题中的

using vs = vector<string>;//注:本题中的vs为vector<string>
inline vs Split(const string& str,char flag,bool saveflag);
inline string Ignore(const string& str,char flag);
inline int to_int(const string& str);
inline string Replace(const string& str,char from,char to);
inline vs FindBrackets(const string& str);
inline string DecodeBrackets(const string& str);
//...

把这些函数封装起来会使代码的可读性和可维护性增加很多。一般来说竞赛代码不会考虑可维护性,但是大模拟还是需要维护一下的。另外vector真是个好东西(尤其在大模拟中)!当然平常滥用vector并且不进行vec.reserve()可能会导致 TLE,不过在大模拟里面我们不需要考虑这些。

然后这道题要我们写一个解释器。一开始咱没有发现代码块可以嵌套......结果重写了两个小时()。有代码块嵌套的情况下,我们其实可以把每个ihu{} hor{}的代码块看作一个函数,而先把代码块封装起来,每次遇到这些语句就执行它的代码块。因为我们的Execute()函数是递归执行的,刚好模拟出了代码块嵌套的效果。于是我们再加上亿点点细节就可以做出本题了。

最后打大模拟真爽。

代码

#include<bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
using vs = vector<string>;
const string chars = "abcdefghijklmnopqrstuvwxyz";
const string block = "_block";
unordered_map<string,int> var;
unordered_map<string,vs> codeblock;
stack<string> nowblock;
vs err;
int functionCnt;
ostream& operator<<(ostream& cout,vs vec){
    for(auto i : vec){
        cout<<i<<" ";
    }
    return cout;
}
inline string NewFunction(){
    return block + to_string(++functionCnt);
}
inline vs Split(const string& str,char flag,bool saveflag){//保留flag
    vs ret;string now;
    string strf = "";
    strf += flag;
    for(auto i : str){
        if(i == flag){
            if(now != "")ret.push_back(now);
            if(saveflag){
                ret.push_back(strf);
            }
            now = "";
        }else{
            now += i;
        }
    }
    if(now != "")ret.push_back(now);
    return ret;
}
inline vs Split(const string& str,const string& flag,bool saveflag){//保留flag
    vs ret;string now;
    bool flg[512] = {0};
    for(auto i : flag)flg[i] = true;
    for(auto i : str){
        if(flg[i]){
            if(now != "")ret.push_back(now);
            if(saveflag){
                string strf = "";strf += i;
                ret.push_back(strf);
            }
            now = "";
        }else{
            now += i;
        }
    }
    if(now != "")ret.push_back(now);
    return ret;
}
inline string Ignore(const string& str,char flag){
    string ret;
    for(auto i : str){
        if(i != flag)ret += i;
    }
    return ret;
}
inline string Ignore(const string& str,const string& flag){
    string ret;
    bool flg[512] = {0};
    for(auto i : flag){
        flg[i] = true;
    }
    for(auto i : str){
        if(!flg[i])ret += i;
    }
    return ret; 
}
inline int to_int(const string& str){
    int ret = 0;
    for(auto i : str){
        ret = ret * 10 + i - '0';
    }
    return ret;
}
inline char FindOP(const string& str){
    for(int i = 0;i < str.size();i++){
        if(str[i] == ':')return str[i+1];
    }
    return '0';
}
inline string Replace(const string& str,char from,char to){
    string ret;
    for(auto i : str){
        if(i == from){
            ret += to;
        }else{
            ret += i;
        }
    }
    return ret;
}
inline vs FindBrackets(const string& str){
    vs ret;bool added = false;string pre,inner;
    for(auto i : str){
        if(!added){
            if(i != '[')pre += i;
        }else{
            if(i != ']')inner += i;
        }
        if(i == '['){
            added = true;
        }else if(i == ']'){
            break;
        }
    }
    ret.push_back(pre),ret.push_back(inner);
    return ret;
}
inline bool IsNum(const string& str){
    for(auto i : str){
        if(i < '0' || i > '9')return false;
    }
    return true;
}
inline string DecodeBrackets(const string& str);
inline int Calc(const string& str){
    int ret = 0;
    vs line = Split(Ignore(str,' '),"+-",true);
    line.insert(line.begin(),"+");
    int opt = 1;
    for(auto i : line){
        if(i == "+"){
            opt = 1;
        }else if(i == "-"){
            opt = -1;
        }else{
            if(IsNum(i)){
                ret += to_int(i) * opt;
            }else{
                ret += var[DecodeBrackets(i)] * opt;
            }
        }
    }
    return ret;
}
inline vs pop_front(const vs& invs){
    vs ret;
    for(int i = 1;i < invs.size();i++){
        ret.push_back(invs[i]);
    }
    return ret;
}
inline string DecodeBrackets(const string& str){
    vs brr = FindBrackets(str);
    if(brr[1] == "")return brr[0];
    if(brr.size() > 2)err.push_back("Brackets_vs size != 2");
    return brr[0] + to_string(Calc(brr[1]));
}
inline vs SplitBlock(const string& code){
    string nows;vs ret;
    int now = 0;
    for(auto i : code){
        if(now == 0){//清除前导空格
            if(i != ' ' && i != '{'){
                now = 1;
                nows += i;
            }
        }else if(now == 1){//读取命令,如hor
            if(i == ' '){
                now = 2;
                ret.push_back(nows);nows = "";
            }else{
                nows += i;
            }
        }else{
            nows += i;
        }
    }
    vs cache = Split(Ignore(nows,' '),',',false);
    for(auto i : cache){
        ret.push_back(i);
    }
    return ret;
}
inline void OutPut(const string& code){
    vs s2 = Split(code,' ',false);string str;
    for(int i = 1;i < s2.size();i++){
        str += s2[i];//ignore yosoro
    }
    if(str == "endl"){
        cout<<endl;return ;
    }
    cout<<Calc(str)<<" ";
    return ;
}
inline void SetVar(const string& code){
    vs varline = SplitBlock(code);
    //varline :    ":set a 1 "  ,should size 3
    var[DecodeBrackets(varline[1])] = Calc(varline[2]);
    return ;
}
inline bool Judge(const vs& ihu){
    //ihu :   "ihu eq chika 1"   ,should size 4
    if(ihu[1] == "lt"){
        return Calc(ihu[2]) < Calc(ihu[3]);
    }else if(ihu[1] == "gt"){
        return Calc(ihu[2]) > Calc(ihu[3]);
    }else if(ihu[1] == "le"){
        return Calc(ihu[2]) <= Calc(ihu[3]);
    }else if(ihu[1] == "ge"){
        return Calc(ihu[2]) >= Calc(ihu[3]);
    }else if(ihu[1] == "eq"){
        return Calc(ihu[2]) == Calc(ihu[3]);
    }else if(ihu[1] == "neq"){
        return Calc(ihu[2]) != Calc(ihu[3]);
    }else{
        err.push_back("In judge undefined "+ihu[1]);
    }
    return false;
}
inline void PreExecute(const string& code){
    if(code == "")return ;
    const string nowblk = nowblock.top();
    if(Ignore(code,' ')[0] == '{'){
        nowblock.push(NewFunction());
        codeblock[nowblock.top()].push_back(Ignore(code,"{}"));
    }else if(Ignore(code,' ')[0] == '}'){
        const string blockname = nowblock.top();
        nowblock.pop();
        codeblock[nowblock.top()].push_back(blockname);
    }else{
        codeblock[nowblk].push_back(Ignore(code,"{}"));
    }
    return ;
}
inline void ExecuteBlock(const string& code);
inline void Execute(const string& code);
inline void Execute(const string& code){
    if(code == "vars"){
        return ;//do nothing
    }if(FindOP(code) == 'y'){
        OutPut(code);
    }else if(FindOP(code) == 's'){
        SetVar(code);
    }else if(code[0] == '_'){//execute blocks
        ExecuteBlock(code);
    }else{
        err.push_back("unexpected "+code);
    }
    return ;
}
inline void ExecuteBlock(const string& blockname){
    const vs codes = pop_front(codeblock[blockname]);
    const string typeFlag = SplitBlock(codeblock[blockname]  [0])[0];
    if(typeFlag == "main"){//main只需要依次执行
        for(auto i : codes){
            Execute(i);
        }
    }else if(typeFlag == "vars"){
        //什么都不需要做
    }else if(typeFlag == "ihu"){
        if(Judge(SplitBlock(codeblock[blockname]  [0]))){
            for(auto i : codes)Execute(i);
        }else{
            //什么都不做
        }
    }else if(typeFlag == "hor"){
        const vs& blockHead = SplitBlock(codeblock[blockname]  [0]);
        int& ivar = var[DecodeBrackets(blockHead[1])];
        const int stvar = Calc(blockHead[2]);
        const int edvar = Calc(blockHead[3]);
        for(ivar = stvar;ivar <= edvar;ivar++){
            for(auto i : codes)Execute(i);
        }
    }else if(typeFlag == "while"){
        const vs& blockHead = SplitBlock(codeblock[blockname]  [0]);
        while(Judge(blockHead)){
            for(auto i : codes)Execute(i);
        }
    }
    return ;
}
int main(){
    freopen("P3695.in","r",stdin);
    freopen("P3695.out","w",stdout);
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    string incode;
    nowblock.push("_main");PreExecute("main");
    while(getline(cin,incode)){
        PreExecute(incode);
    }
    ExecuteBlock("_main");
    return 0;
}
此作者没有提供个人介绍。
最后更新于 2026-09-10