【教学类-06】20220119 VS python 20以内加减法(不重复)

背景需求——幼小衔接适应

疫情危机,孩子们哪里也不敢去。为了丰富幼儿的寒假生活。搭档程老师想给孩子布置一些打卡任务,运动、绘画、写字等,她找到网上一份20以内的加减法7页纸的题目想发给家长打印,但无法下载(收费 )。我想既然我会一点python,自己批量一些题应该不难吧。

出现问题——批量加减法有重复

加减法练习,包括了前书写(名字、日期)和思维练习(数字、计算),有助于大班孩子们感知一年级的题型样式,逐步适应小学数学模式。因此我尝试拷贝、修改以前下载的加减法python代码,顺利完成了Word模板的填写。但是,前期孩子们说“有题目是一样的”的现象非常明显(相同的题目相邻出现) ——本次批量了360题,用Excel查找重复值后,只留下了215条不重复的,41%的题目都是重复的。为了删除重复题,又费了不少时间。

解决途径——求教IT高手

IT网管员马先生提供了技术支持,经过三轮测试,制作了一个代码行数较少的“20以内加减法不重复”的代码,测试后的确实现了预期需求

一、代码(简易版)

# -*- coding: utf-8 -*-  
""" 
@author: 马清新
@file: 马清新注释版 不重复的20以内加减法(最多190题).py
@time: 2022/1/19 8:42 
"""

import random

# regList用于存储合规的加减法表达式(正确列式)
regList = []
# answer用于存储合规的加减法表达式(正确答案)
answer = []
maxNum = int(input('请输入加法和最大值(10以内 20以内'))#输入最大值
regnum = int(input('请输入出题数量(20以内取值范围小于等于190题)'))#输入题目数量

# 加减法 
i = regnum  # i=出题数量  循环记数使用
while i > 0:  #当数量大于0,执行
     try:  #try……except含义:try没有异常时,处理器不执行, 
        # regStr = '' #把整数算式转换成字符串使用的,初始情况下让它为空比较保险
        # 随机 要求和值范围内的 随机数
        a = random.randint(1,maxNum)
        # 随机 要求和值范围内的随机数,要求两随机数和不得大于maxNum
        b = random.randint(1,(maxNum-a))
        # 比较两各随机数大小,如a<b使用加法,a>b则使用减法,c是记录加减法的答案
        if a <= b: #如果第1个数小于等于第2个数
            c= a + b  #第3个数=第1个数+第2个数
            # 将加减法表达式转换为字符串模式 str 
            regStr = str(f'{a} + {b} ={c}')
            # 将加减法表达式含答案转换为字符串模式
            answerStr = str(f'{a} + {b} = ')#打印结果“第1个数+第2个数” answer是要被打印的,所以C为空
        else:
            c = a - b #如果第3个数=第1个数-第2个数(如果第1个数大于第2个数)
            regStr = str(f'{a} - {b} ={c}')
            answerStr = str(f'{a} - {b} = ')#打印结果“第1个数-第2个数”
        # 利用if not in 去重,符合去重条件的保存,不符合的从头执行。
        if regStr not in regList:#如果整数转字符串的题目 不在regList的列表内
            # append 是列表的方法,是在列表的结尾添加新的元素,元素就是咱们符合要求的算式
            regList.append(regStr)#regList是不含答案的列表,每次出题学生得到的是没答案的算式。
            answer.append(answerStr)#这个是带了答案的符合要求算式的列表,老师手上的是有答案的,本题教师需要的没有答案的,所以C为空。
            # regList和answer都是空列表,为存放找到算式预留的,
            # 两个唯一的区别就是一个有答案给老师answerStr,一个没答案给学生regStr
            i -= 1 #找到了符合要求的算式,见19行题目数 需要减掉1,因为i的初始值是需要得到算式的数量,每找到一个就减一个,直到0
        else:
            continue
        
        
     # 随机过程中可能会出现随机数报错
     # 例如 a随机为19,b的随机范围变成rangeint(1,1)这种情况系统会报错,需要进行处理
     except ValueError:  # try……except含义:try有异常时, 执行except搜索异常处理器,找异常声明,没有找到,异常被保存。
         # 打印错误 打印ValueError的字样
         print(ValueError)
         # 继续从头执行程序
         continue

        
# 打印带答案的算术加减法
for _ in answer :#最后得到的符合不重复算式的列表answer,
    print(_) #print(_)循环打印出来验证一下
# 确认加减法出题量 验证列表的长度,验证一下总共是否与需求的算式数量一致NUM
print(len(answer))

# 这里的_是一种省略变量的方法,就是系统随便分配一个变量,用完就回收了,免得再定义一个了 可以用i 或者j这些变量去代替。这里的_是一种省略变量的方法,就是系统随便分配一个变量,用完就回收了,免得再定义一个了 可以用i 或者j这些变量去代替。


# 1月19日版本
# 保存为TXT文件(在默认打开文件夹下,手动拷贝到Word里
#str_title = '2.txt' # 保存文件名
#with open('2.txt','w') as f:#  打开TXT文件
#    for a in answer:#  #循环查找答案的内容
#        f.write(str(a)+'\n')# 写入答案内容并回车
#f.close()# #关闭TXT

# 2月4日版本 保存带数字提示的题目,如5以内加减法题(8题) 但是输入的题目超过最大不重复的题目数量后,就会报错,所以这段代码废弃。
str_title = '%d以内的加减法题(共%d题).txt' % (maxNum, len(answer)) # 保存带数字提示的题目
with open(str_title,'w') as f:#  打开TXT文件
    for a in answer:#  #循环查找答案的内容
        f.write(str(a)+'\n')# 写入答案内容并回车
f.close()# #关闭TXT


 


作者后续优化思路:

     第一次设计的程序,是用足够多的异常强逼出最后不重复的算式小,要的和小还行,超过100效率就低了。所以20以内题目超过190题就报错,我想了好一阵如何去除报错问题。 

    昨天那个代码,把数字和加减法都用随机的方式生成,目的是保证生成足够多的算式就可以。想去掉重复,最好是做题库,然后随机索引去抽题,可以分开加减法。其实不用random做,问题也许更简单,那个重复1000次报错,其实就是算法本身缺陷造成的。今天我利用随机数比大小去做去重,但是发现这个只是正常的操作方法,算法上有漏洞,   

   拿20以内的加减法来说,去掉减法答案为0的题,算法如下,建立一个整数列表 范围 0至19,这样可以保证列表索引和列表元素一致.

    然后设置双层循环次数,第一层从索引1开始,到索引20/2,底层索引刚从1到20-1(1用i,做变量),这样每个循环得到一个加法算式和减法算式成对出现,这样当顶层循环到20/2的位置的时候,所有非重复的算式加减法都出来了

   可以根据自己的需要建立加法算式列表和减法算式列表,当需要抽题的时候,直接random一下就可以了。这样就不存在异常的情况了

最终版算法,合格靠谱了,算是正轨算法吧(加了最大不重复算式统计值)

一、代码(正式版 以此为准)

# -*- coding: utf-8 -*-  
""" 
@author: 马清新
@file: 马清新 20以内加减法(最大不重复算式值).py
@time: 2022/1/20 20:15

# 特别说明
1.根据预测试:10以内不重复132题,20以内不重复的462,50以内2652 100以内10302
样式1:如果20以内的题目数量输入了1000题,但它最终只会出现380题(共生成不重复380,最大不重复380)
样式2:如果50以内输入1000题,它最终会出现1000题(共生成不重复1000),但实际最多可以出现的1824题(最大不重复2450)

2.本次的最大值和题数可以无限大,但是考虑到电脑算力和生成时长,建议不要超过1000以内(999000题).

3.X以内 两个数加减法(X+Y= X-Y= )的最大不重复题目数量:	
X以内	加法题	减法题	加减法乱序题	排除答案0
  5	   21	  21	  42	       36
 10	   66	  66	  132	       121
 20	   231	  231	  462	       441
 50	   1326	  1326	  2652	       2601
100	   5151	  5151	  10302	       10201
"""

import random

sumMax = int(input('请输入算式最大和:'))
regNum = int(input('请输入需要生成算式的数量:'))
# 生成1个列表,列表从0开始,到算术最大和结束,因为range函数包左不包右,因此如果要包括算式最大和,必须+1
# range函数从0开始,这样列表元素和列表索引一致,减轻算法的难度
numList = [x for x in range(0,sumMax+1)]
# resultList列表用于保存最后最大数量的合规算术式
resultList = []
for x in numList[0:]:
    # 从列表第x个元素开始到列表最后一个元素进行循环遍历
    for y in numList[x:]:
        # 加和减 列表元素开始时存在两个元素相等的情况,由于加法交换律会产生重复,所以单独进行区分
        if (x == y) and (x + y <= sumMax)and (y != 0): # X或Y两者一个或者两个都不能0。没有0+0,0-0
            tempStr = str(x) + ' + ' + str(y) + ' = '
            resultList.append((tempStr, (x+y)))
            tempStr = str(x) + ' - ' + str(y) + ' = '
            resultList.append((tempStr, (x-y)))
         #加和减 查找 x + y < 算式最大和的加减法,此处考虑加法交换律,减法中去除了相减为0的情况,因为此处y>x
        elif x + y <= sumMax and (y != 0):# 第一位或者第二位都不为0,也就是没有
            tempStr = str(x) + ' + ' + str(y) + ' = '
            resultList.append((tempStr, (x+y)))
            tempStr = str(y) + ' + ' + str(x) + ' = '
            resultList.append((tempStr, (x+y)))
            tempStr = str(y) + ' - ' + str(x) + ' = '
            resultList.append((tempStr, (y-x)))
        # 考虑循环后期,x+y会打印算式要求的最大和,但是减法符合算式要求,处于严谨的考虑没有使用else
        # 减法 此处可以考虑直接使用else
        elif y - x >= 0 and y != 0: # y可能等于x ,答案为0,但没有0-0
            tempStr = str(y) + ' - ' + str(x) + ' = '
            resultList.append((tempStr, (y-x)))
        elif y - x == 0 :#等数 相加 相减等于0,不需要的话,此段注释掉
            tempStr = str(y) + ' + ' + str(x) + ' = '#减法类型3 y-x=0   
            resultList.append((tempStr, (y+x)))# 带答案的题目,如0+0=0,
            tempStr = str(y) + ' - ' + str(x) + ' = '#减法类型3 y-x=0   
            resultList.append((tempStr, (y-x)))# 带答案的题目,如0-0=0,

# 建立最终符合最终要求的算式列表9
selectList = []
if regNum > len(resultList):#输入题数大于实际需求,就用shuffle洗牌,
    print(f'您的需求大于最大算式生成数量!最大生成算式数量为{len(resultList)}')
    i = len(resultList)
    for _ in resultList:
        selectList.append(_)
    random.shuffle(selectList)    #shuffle 洗牌算法,把列表所有元素打乱,随机排列
    for _ in selectList:
        # 可选打印带答案的和不带答案啊
        print(_[0])# 不带答案
        # print(f'{_[0]}{_[1]}')# 带答案
else:#输入题数小于实际需求,代码自动随机抽取,不会排序,
    i = regNum
    selectList = random.sample(resultList,i)
    for _ in selectList:
        # 可选打印带答案的和不带答案啊
        print(_[0])# 不带答案
        # print(f'{_[0]}{_[1]}')# 带答案

# 验证生成算式数量
print(f'共生成不重复的算式{len(selectList)}')
print(f'最大不重复的算式{len(resultList)}')

# 保存为TXT文件(在默认打开文件夹下,手动拷贝到Word里1
# str_title = '2.txt' # 保存文件名60
# with open('2.txt','w') as f:#  打开TXT文件
#     for a in selectList:#  #循环查找答案的内容8
#         # f.write(str(a[0])+'\n')# 写入答案内容并回车 a[0]没有答案 
#         f.write(str(a[0])+'\n')#写入答案内容并回车 a[1]有答案
# f.close()# #关闭TXT、

# 2月4日修改TXT文件名称
str_title = '%d以内的加减法题(共%d题).txt' % (sumMax, len(resultList)) # 保存带数字提示的题目
with open(str_title,'w') as f:#  打开TXT文件
    for a in selectList:#  #循环查找答案的内容
        f.write(str(a[0])+'\n')# 不带答案
        # f.write(str(a[1])+'\n')#只有答案
        # f.write(str(a[0])+str(a[1])+'\n')#有题目有答案  TXT里面是题目+答案,终端显示题目 无答案,因为上面选了(0)
f.close()# #关闭TXT

二、代码运行

(一 )运行 

(二)运行 第一个问题,输入“X以内加减法”中的X数字20

 (三)运行第二个问题输入任意数字

 (四)VS界面结果

  (五)TXT结果

 打印模板——Word打印模板制作(后期尝试能直接生成Word模板,现在先手动)

1、题目样张

 2、统一抬头(在页眉里设置)

  3、作业页码(插入页码)

   4、把TXT的数字批量拷贝到Word里

   5、制作四列分栏

 

 

   6、字体变大

 7、添加外框

8、462题可以布满15张差一些

教学反思——抓牢基础,万变不离

感谢马先生写的代码,解决了我在批量加减法题中的题目重复问题,从实际需求中去学习如何解读代码内容,让记忆中的基础知识被唤醒,真正地理解其实用性。从直观效果中加深记忆和理解。鸣谢大师!

这是阿夏第7个实际运用到幼儿园教学中的Python自动化案例(教学类-06),希望能通过借鉴、实验、修改,将Python运用到幼儿园办公工作和幼儿教学中,提高工作效率,推动幼儿个性化学习和层次性学习成效。   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿夏reasonsummer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值