• 软工第二次作业


    GIT地址 https://github.com/Cpu8285
    GIT名称 Cpu8285
    学号后五位 64222
    博客地址 https://www.cnblogs.com/565118008a/
    作业地址 https://www.cnblogs.com/ChildishChange/p/10398212.htm

    1.配置环境

    试了很多钟方法,VS2017无法安装,可能我的电脑不适配,然后改下VS2015,居然这么久,惊了。。。

     2.代码

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 mt19937 mt(time(0)); // 随机数生成器
      6 
      7 map<int, char> op; // 运算符id及其符号映射
      8 map<int, int> pri; // 运算符id及其优先级映射
      9 // 10表示加号   运算优先级为 0
     10 // 11表示减号   运算优先级为 0
     11 // 12表示乘号   运算优先级为 1
     12 // 13表示除号   运算优先级为 1
     13 // 14表示左括号 运算优先级为 2
     14 // 15表示右括号 运算优先级为 2
     15 
     16 // 运算数结构体,id为运算数的位置,val为运算数的值
     17 struct node{
     18     int id, val;
     19     node(int id = -1, int val = -1):id(id), val(val){}
     20 };
     21 
     22 // tot:逆波兰表达式的长度,operatorNum:运算符个数
     23 // operandNum:运算数的个数,bracketNum:括号对数,ans:运算式最终答案
     24 // hasBracket:某个数字处是否有括号,-1表示无括号,14表示左括号,15表示右括号
     25 // operators:对应位置的运算符种类 operands:表示对应位置运算数的值
     26 // RPN:存储逆波兰表达式 fac:存储某个数的约数
     27 // opr:中缀表达式转后缀表达式时的运算符栈
     28 // opd:中缀表达式转后缀表达式时的运算数栈
     29 
     30 int tot, operatorNum, operandNum, bracketNum, ans;
     31 int hasBracket[15], operators[15], operands[15];
     32 int RPN[55], fac[105];
     33 stack<int> opr;
     34 stack<node> opd;
     35 
     36 // 初始化函数零:初始化运算符 id 符号 以及运算优先级,并且重定向输出
     37 void init0(){
     38     op[10] = '+', op[11] = '-';
     39     op[12] = '*';
     40     op[14] = '(', op[15] = ')';
     41     pri[10] = 0, pri[11] = 0;
     42     pri[12] = 1, pri[13] = 1;
     43     pri[14] = 2, pri[15] = 2;
     44     freopen("../result.txt", "w", stdout);
     45 }
     46 
     47 // 初始化函数一:在每次调用solve()时进行初始化
     48 void init1(){
     49     tot = 0;
     50     for(int i = 0; i < 15; ++i){
     51         operators[i] = -1;
     52         operands[i] = -1;
     53         hasBracket[i] = -1;
     54     }
     55     while(!opr.empty()) opr.pop();
     56     while(!opd.empty()) opd.pop();
     57 }
     58 
     59 // 初始化函数二:在每次调用getOperands()时进行初始化
     60 void init2(){
     61     tot = 0;
     62     while(!opr.empty()) opr.pop();
     63     while(!opd.empty()) opd.pop();
     64 }
     65 
     66 // 获取运算数的值的函数,如果返回 true 则表示获取成功,否则表示获取失败
     67 bool getOperands(){
     68     init2();
     69     // 将中缀表达式转换成后缀表达式(也就是逆波兰表达式)
     70     if(hasBracket[0] != -1) opr.push(hasBracket[0]);
     71     RPN[tot++] = 0;
     72     for(int i = 1; i < operandNum; ++i){
     73         while(true){
     74             if(opr.empty() || opr.top() == 14 || pri[operators[i - 1]] > pri[opr.top()]){
     75                 opr.push(operators[i - 1]);
     76                 break;
     77             }
     78             RPN[tot++] = opr.top();
     79             opr.pop();
     80         }
     81         if(hasBracket[i] == 14){
     82             opr.push(hasBracket[i]);
     83         }
     84         RPN[tot++] = i;
     85         if(hasBracket[i] == 15){
     86             while(opr.top() != 14){
     87                 RPN[tot++] = opr.top();
     88                 opr.pop();
     89             }
     90             opr.pop();
     91         }
     92     }
     93     while(!opr.empty()){
     94         RPN[tot++] = opr.top();
     95         opr.pop();
     96     }
     97     // 转换成逆波兰表达式后便可以进行尝试填数
     98     for(int i = 0; i < tot; ++i){
     99         // 如果为运算数则随机为其赋值
    100         if(RPN[i] < 10){
    101             int x = mt()%66 + 1;
    102             operands[RPN[i]] = x;
    103             opd.push(node(RPN[i], x));
    104             continue;
    105         }
    106         //如果为除法,要将除数随机分配为被除数的一个因子
    107         //如果为减法,要注意减数不能大于被减数
    108 
    109         if(RPN[i] == 13){
    110             node b = opd.top(); opd.pop();
    111             node a = opd.top(); opd.pop();
    112             if(a.val%b.val == 0){
    113                 opd.push(node(-1, a.val/b.val));
    114                 continue;
    115             }
    116             if(b.id == -1) return false;
    117             int cnt = 0;
    118             for(int j = 1; j <= a.val; ++j){
    119                 if(j >= 100) break;
    120                 if(a.val%j) continue;
    121                 fac[cnt++] = j;
    122             }
    123             int x = mt()%cnt;
    124             operands[b.id] = fac[x];
    125             opd.push(node(-1, a.val/fac[x]));
    126         }else if(RPN[i] == 11){
    127             node b = opd.top(); opd.pop();
    128             node a = opd.top(); opd.pop();
    129             int dt = a.val - b.val;
    130             if(dt <= 0) return false;
    131             opd.push(node(-1, dt));
    132         }else{
    133             node b = opd.top(); opd.pop();
    134             node a = opd.top(); opd.pop();
    135             if(RPN[i] == 10) opd.push(node(-1, a.val + b.val));
    136             if(RPN[i] == 12) opd.push(node(-1, a.val*b.val));
    137         }
    138     }
    139     ans = opd.top().val; opd.pop();
    140     //控制最终运算结果的范围,可根据需要进行调节
    141     if(ans < 0 || ans > 1000) return false;
    142     return true;
    143 }
    144 
    145 bool solve(){
    146     init1();
    147     // 随机生成运算符的个数 3~5 ,及运算数个数 4~6
    148     operatorNum = mt()%3 + 3;
    149     operandNum = operatorNum + 1;
    150     // 随机生成括号个数
    151     bracketNum = min((int)(operandNum/2), (int)(mt()%3 + 2));
    152     // 随机生成运算符的种类
    153     for(int i = 0; i < operatorNum; ++i) operators[i] = mt()%4 + 10;
    154     // 随机生成括号位置
    155     for(int i = 0; i < bracketNum*2; ++i){
    156         int x = mt()%operandNum;
    157         while(hasBracket[x] != -1) x = mt()%operandNum;
    158         hasBracket[x] = 0;
    159     }
    160 
    161     // 根据相对位置确定括号为左括号还是右括号
    162     bool lf = true;
    163     for(int i = 0; i < operandNum; ++i){
    164         if(hasBracket[i] == -1) continue;
    165         if(lf) hasBracket[i] = 14;
    166         else hasBracket[i] = 15;
    167         lf = (!lf);
    168     }
    169 
    170     // 到这里已经将等式预处理成了(a+b)/c*(d-e)的类似形式
    171     // 预处理结束之后,我们就要尝试将 a b c d e 确定为具体的数
    172     if(!getOperands()) return false;
    173 
    174     // 在获取完运算数之后,便可以输出我们得到的等式了
    175     if(hasBracket[0] != -1) printf("(");
    176     printf("%d", operands[0]);
    177     for(int i = 1; i < operandNum; ++i){
    178         if(operators[i - 1] == 13) printf("÷");
    179         else printf("%c", op[operators[i - 1]]);
    180         if(hasBracket[i] == 14) printf("(");
    181         printf("%d", operands[i]);
    182         if(hasBracket[i] == 15) printf(")");
    183     }
    184     printf("=%d
    ", ans);
    185     return true;
    186 }
    187 
    188 
    189 int main(){
    190     // 初始化函数零:初始化运算符 id 符号 以及运算优先级,并且重定向输出
    191     init0();
    192     //读入需要生成的运算式数量
    193     int n;
    197     while(n--) while(!solve()) ;
    198 
    199     return 0;
    200 }

    3.GIT软件上传GITHUB,VS2017无法下载,所以暂时无从下手。

    4·感想

    完成质量有点差,早上八点到晚上九点一直再赶,到后面只是把代码研究了出来,其他根本无从下手,

    融入新事物的能力差,已经养成依赖老师讲解的思维,到自己做的时候就无所适从,这是我的一个很大

    问题。

     

  • 相关阅读:
    CLASS 类 __getattr__
    class多态
    class类 __repr__ 与__str__
    CLASS类继承
    calss 类
    SVN报错:database is locked
    项目:表格打印(字符图网格进阶、rjust、列表中最长的字符串长度)
    项目:口令保管箱,批处理文件配置.bat
    字典方法 setdefault()、pprint;迭代、递归的区别
    项目:在wiki标记中添加无序列表(split、join巩固)
  • 原文地址:https://www.cnblogs.com/565118008a/p/11564827.html
Copyright © 2020-2023  润新知