• 宋晓丽 20190919-6 四则运算试题生成,结对


    此作业的要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/7631]

    代码的git地址[https://e.coding.net/sxl357/f4.git]

    git地址下的功能1.py和功能1.exe用来完成功能1,f4.py和f4.exe用来完成功能2和功能3.

    功能1. 四则运算

    支持出题4个数的四则运算题目,所有题目要求作者有能力正确回答

    > f4
    1+2*3+4=
    ?11
    答对啦,你真是个天才!
    1+2*3+5=
    ?11
    再想想吧,答案似乎是12喔!
    1+2/4-5=
    ?-3.5
    答对啦,你真是个天才!
    ...(一共20道题)
    
    你一共答对4道题,共20道题。
    重难点:
    1.
    给定一个运算式,如何让计算机算出结果?
    给定的运算式属于中缀表达式,将其改为后缀表达式,再计算结果。
    (1)中缀转后缀
    #将中缀表达式转为后缀表达式
    def make_Expression(s):
        operations=[]
        result=''
        front={'+':1,'-':1,'*':2,'/':2}
        for i in s:
            if i in ['+','-','*','/']:#判断是否是操作符
                if len(operations)==0:#栈空,直接入栈
                     operations.append(i)
                elif front[operations[-1]]>=front[i]:#判断栈顶元素和操作符的优先级别
                    while len(operations)>0 and front[operations[-1]]>=front[i]:#持续将栈顶元素弹出并输出,直至遇到低于或等于此操作符的优先级别
                        p=operations.pop()
                        result+=p
                    operations.append(i)
                else:
                    operations.append(i)
            else:
                result+=i#若是数,直接输出
        while len(operations)>0:#将栈中的所有元素依次弹出
            p=operations.pop()
            result+=p
        return result#返回后缀表达式

    (2)计算后缀表达式

    #计算后缀表达式
    def make_Value(s):
        lists=[]
        for i in s:
            if i in ['+','-','*','/']:
                b=float(lists.pop())#先弹出的是b,下个弹出的是a
                a=float(lists.pop())
                c=0
                if i=='+':#判断做哪则运算
                    c=a+b
                elif i=='-':
                    c=a-b
                elif i=='*':
                    c=a*b
                else:
                    c=a/b
                lists.append(c)#得到的结果压入栈中
            else:
                lists.append(i)
        return lists[0]

    2.如何随机生成运算式(3个运算符,4个操作数)?

    这对于我们来说是个大问题,查资料,询问 师哥师姐,了解到random.randint(a,b)用于生成一个指定范围内的整数n

    #随机生成运算式
    from random import randint #random.randint(a,b)用于生成一个指定范围内的整数n,其中a<=n<=b
    # 定义类
    class Expression:
        # 生成运算式
        def expre(self):#在类里定义函数必须传入self,指的是类实例对象本身
            exp = []
            for j in range(0,7):  #range(a)=[0,1,2,3,...,a-1]
                if j % 2 != 0:#通过模2,生成带3个运算符4个10以内数字的表达式
                    operators = ['+', '-', '*', '/']
                    exp.append(operators[randint(0, len(operators) - 1)])  #随机生成运算符
                else:
                    exp.append(str(randint(1, 9)))  #随机生成操作数
            expression = ''.join(exp)
            return expression
    generate=Expression() #定义对象
    expression = generate.expre()#调用generate()函数,生成运算式

    3.如何循环出题,并验算结果,给出反馈?

    先生成运算式,然后调用转后缀,计算后缀的函数 ,得到正确结果,与用户输入的对比,给出反馈,循环20次,并利用全局变量累积答对的题的数目。

    #出20道考题,判断用户结果是否等于正确答案,实现功能一
    def question():
        num = 0
        global correctNumber  # 定义全局变量,统计答对的次数
        while num <20:
            generate=Expression() #定义对象
            expression = generate.expre()#调用generate()函数,生成运算式
            print(expression + "=")
            expression1 = make_Expression(expression)  # 将中缀表达式转换为后缀表达式
            result = make_Value(expression1)  # 计算后缀表达式的值
            userAnswer = input()  # 输入你的答案
            if '?' in userAnswer:
                userAnswer = userAnswer.replace('?', '')#str.replace(old,new,max)方法,把字符中的old替换成new,且替换不超过max次
            if (float(userAnswer) == float(result)):  # 判断用户结果是否和正确答案相等
                correctNumber += 1
                print("答对了,你真是个天才!")
            else:
                result = str(result)
                print('再想想吧,答案似乎是' + result + '喔!')
            num += 1
        correctNumber = str(correctNumber)
        print("你一共答对" + correctNumber + "道题,共20道题。")

    4.如何定义此时的主函数?

    #定义主函数
    def main(argv):
            question()#实现功能一
    
    
    #主函数
    if __name__ == "__main__":
        main(sys.argv[1:])

    运行测试截图

    功能2 支持括号

    > f4
    1+2*(3+4)=
    ?15
    答对啦,你真是个天才!
    (1+2)*3+5=
    ?11
    再想想吧,答案似乎是14喔!
    ((1/2)-4)*5=
    ?-17.5
    答对啦,你真是个天才!
    ...(一共20道题)
    
    你一共答对4道题,共20道题。

    重难点

    1.中缀转后缀时,有括号怎么办?

    左括号可以直接入栈,但遇到右括号时,遇到右括号,持续将栈顶元素弹出并输出,直至遇到左括号

     for i in s:
            if i in ['+','-','*','/','(',')']:#判断是否是操作符
                if i=='(':#遇到左括号,将其直接放入栈中
                    operations.append(i)
                elif i==')':#遇到右括号,持续将栈顶元素弹出并输出,直至遇到左括号
                    while (len(operations)>0 and operations[-1]!='(' ):#-1表示列表的最后一个元素,即栈顶
                        p=operations.pop()
                        result+=p
                    operations.pop()#左括号只弹出不输出
                elif len(operations)==0:#栈空,直接入栈
                     operations.append(i)
                elif front[operations[-1]]>=front[i]:#判断栈顶元素和操作符的优先级别
                    while len(operations)>0 and front[operations[-1]]>=front[i]:#持续将栈顶元素弹出并输出,直至遇到低于或等于此操作符的优先级别
                        p=operations.pop()
                        result+=p
                    operations.append(i)
                else:
                    operations.append(i)
            else:
                result+=i#若是数,直接输出

    2.何时何地生成括号?

    在生成运算式的类中,生成了不带括号的运算式后,随机生成0或1,0就表示不插入括号,1表示插入括号,此时调用生成括号的函数,在该函数中,用枚举法确定括号的位置,然后根据随机数选择其中一种,将括号插入,最后返回带括号的表达式。

      is_need_brackets = randint(0, 1) # 判断是否要括号
            if is_need_brackets:#添加括号
                expression = ''.join(self.make_brackets(exp))#.join()将序列中的元素以指定的字符连接生成一个新的字符串
                                                                    #加括号时,调用生成括号表达式的函数,得到一个带括号的运算式
            else:#不添加括号
                expression = ''.join(exp)
    # 生成括号表达式
        def make_brackets(self,exp):#传入由运算符和数字组成的列表
            expression = []
            # 可能有一对括号,也可能有两对括号,所以最多有11个位置可以添加括号
            #经过枚举,共有10种可能的添加方式
            # 0表示直接将运算符或数字传入生成式,1表示在生成式加入左括号,2表示在生成式加入右括号,-1表示不作任何处理
            judge_position= [
                                  [1, 0, 0, 0, 2, 0, 0, 0, 0, -1, -1],
                                  [1, 0, 0, 0, 0, 0, 2, 0, 0, -1, -1],
                                  [0, 0, 1, 0, 0, 0, 2, 0, 0, -1, -1],
                                  [0, 0, 1, 0, 0, 0, 0, 0, 2, -1, -1],
                                  [0, 0, 0, 0, 1, 0, 0, 0, 2, -1, -1],
                                  [1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 2],
                                  [1, 1, 0, 0, 0, 2, 0, 0, 2, 0, 0],
                                  [1, 0, 0, 1, 0, 0, 0, 2, 2, 0, 0],
                                  [0, 0, 1, 1, 0, 0, 0, 2, 0, 0, 2],
                                  [0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 2]
                              ]
            position = randint(0,9)
            if exp:
                i = 0
                for j in judge_position[position]:#调用上述列表
                    if j ==0:
                        expression.append(exp[i])
                        if i < len(exp):
                            i += 1
                    elif j ==1:
                        expression.append('(')
                    elif j ==2:
                        expression.append(')')
            return expression

    运行测试截图

     

    功能3 限定题目数量,"精美"打印输出,避免重复

    >f4 -c 3
    1+2*(3+4)=                     15
    (1+2)*3+5=                     14
    ((1/2)-4)*5=                   17.5
    >f4 -c -200
    题目数量必须是 正整数。
    >f4 -c 3.5
    题目数量必须是 正整数。
    >f4 -c test
    题目数量必须是 正整数。
    重难点
    1.如何规范化输出?
    print('%-15s %-15s' % (expression, result))  # 规范输出格式

    2.循环体

    # 答案与题目横向对齐,使输出规范化,实现功能三
    def normal(num):
        i = 0
        while i < num:
            generate = Expression()
            expression = generate.expre()
            expression1 = make_Expression(expression)  # 将中缀表达式转换为后缀表达式
            result = make_Value(expression1)  # 计算后缀表达式的值
            expression=expression+"="
            print('%-15s %-15s' % (expression, result))  # 规范输出格式
            i += 1

    3.如何与功能2区分?

    在主函数中判断‘-c’是否在输入的命令行参数里,在则功能3,否则功能2.

    4.如何在输入的命令行参数是负数或者小数时报错?

     count=float(sys.argv[2]) # 获取生成题目的个数
            if count >=1:
                normal(count)

    5.主函数

    #定义主函数
    def main(argv):
        if '-c' in sys.argv:  # 实现功能三
            count=float(sys.argv[2]) # 获取生成题目的个数
            if count >=1:
                normal(count)
            else:
                print("题目数量必须是正整数。")
        else:
            question()#实现功能一二
    
    
    #主函数
    if __name__ == "__main__":
        main(sys.argv[1:])

    运行测试截图

     

     

    总结

    完成这个作业真的是花了很多功夫,因为自己的无知,很多时间都是在做无效的工作,但通过这次学习,我更加清楚了自己的弱势所在,更明白了该怎么去学习,谢谢前面人的工作,使我的学习有迹可循,在此特别感谢我的结对小伙伴梁梦瑶,能在我无比焦躁时安慰我的情绪,和我一起学习,一起努力。

     
  • 相关阅读:
    【ZOJ3195】Design the City-LCA算法
    【ZOJ3195】Design the City-LCA算法
    【POJ1330】Nearest Common Ancestors-LCA算法
    【POJ1330】Nearest Common Ancestors-LCA算法
    【POJ3237】Tree-树链剖分
    【POJ3237】Tree-树链剖分
    【SPOJ375】Query on a tree-树链剖分
    perl 回调必须是函数引用
    运行复制的ZooKeeper 部署
    运行复制的ZooKeeper 部署
  • 原文地址:https://www.cnblogs.com/simpleli66/p/11586058.html
Copyright © 2020-2023  润新知