需求
朋友担心小孩暑假玩疯了,让我弄点小学一年级数学题给小孩做,要求:
- 就是简单的口算式子
- 可以打印成 A4 纸
- 有答案
根据要求,我觉得最简单的办法,就是生成一个内容用 tab 分隔开的 txt 文件,然后手工复制到排版好的 Excel 文件里面直接打印即可。
原始代码
#coding: utf-8
"""本代码来自第一感觉,使用函数实现。添加问题类型时,直接修改 main() 的 question_list 语句即可
"""
import random
def question_1():
"""生成 100 以内退位减法"""
minuend = random.randint(11,98)
units = minuend % 10
while units==9 :
minuend = random.randint(11,98)
units = minuend % 10
subtrahend = random.randint(units+1,9)
answer = minuend - subtrahend
return ("%d - %d = " % (minuend, subtrahend), str(answer))
def question_2():
"""生成两位数加法"""
num1 = random.randint(10, 99)
num2 = random.randint(10, 99)
answer = num1 + num2
return ('%d + %d =' % (num1, num2), str(answer))
def question_3():
"""生成两位数减两位数"""
minuend = random.randint(11,99)
subtrahend = random.randint(10, minuend)
answer = minuend - subtrahend
return ("%d - %d = " % (minuend, subtrahend), str(answer))
def write_it(questions, answers, output_file):
format_items(questions)
format_items(answers)
f = open(output_file, 'w')
f.write("".join(questions))
f.write("\n\n\n")
f.write("".join(answers))
f.close()
def format_items(items, number_per_line = 4):
"""用换行、tab 美化化输出结果,方便之后导入 excel"""
for i,a in enumerate(items):
if i % number_per_line == number_per_line - 1:
items[i] = a + "\n"
else:
items[i] = a + "\t"
def main(output_file, question_type = 1):
"""question_type取值:1 到 3 """
questions = []
answers = []
question_generator = [question_1, question_2, question_3]
for x in range(80):
question, answer = question_list[question_type - 1]()
print( question)
questions.append(question)
answers.append(answer)
print("now write it")
write_it(questions, answers, output_file)
if __name__ == '__main__':
output_file = "out.txt"
main(output_file)
refactoring
引入 with 语句处理文件
以便在发生异常的时候自动关闭资源。将
f = open(output_file, 'w')
f.write("".join(questions))
f.write("\n\n\n")
f.write("".join(answers))
f.close()
改为
with open(output_file, 'w') as f:
f.write("".join(questions))
f.write("\n\n\n")
f.write("".join(answers))
改成混合出题
单一类型题目指定生成,不如直接改成混合生成各类题型,并可以指定各种题型出现的概率。这可以直接利用 python 的 random.choices()
函数实现,请注意该函数的返回值是个 list ,main() 函数修改如下:
def main(output_file, number = 80):
...
question_generator = [question_1, question_2, question_3]
for x in range(number):
which = random.choices([1,2,3], [0.2, 0.4, 0.4])[0] # 各类型题目概率
question, answer = question_generator[which-1]()
...
最终成果
最后,给每个题目添加序号,以便打印出来的题目可以快速找到答案。完整最终代码如下:
#coding: utf-8
"""本代码实现小学一年级数学题目(主要是100以内加减法)的自动出题
"""
# 下一步计划:
# - 添加网络框架(比如 flask),实现在线测试网站
# - 允许选择难度、题型
# - 自动汇总错题
# - 需要登录,以便记录每个人自己的练习情况
import random
def question_1():
"""生成 100 以内退位减法"""
minuend = random.randint(11,98)
units = minuend % 10
while units==9 :
minuend = random.randint(11,98)
units = minuend % 10
subtrahend = random.randint(units+1,9)
answer = minuend - subtrahend
return ("%d - %d = " % (minuend, subtrahend), str(answer))
def question_2():
"""生成两位数加法"""
num1 = random.randint(10, 99)
num2 = random.randint(10, 99)
answer = num1 + num2
return ('%d + %d =' % (num1, num2), str(answer))
def question_3():
"""生成两位数减两位数"""
minuend = random.randint(11,99)
subtrahend = random.randint(10, minuend)
answer = minuend - subtrahend
return ("%d - %d = " % (minuend, subtrahend), str(answer))
def write_it(questions, answers, output_file):
format_items(questions)
format_items(answers)
with open(output_file, 'w') as f:
f.write("".join(questions))
f.write("\n\n\n")
f.write("".join(answers))
def format_items(items, number_per_line = 4):
"""用换行、tab 美化化输出结果,并添加序号,方便之后导入 excel"""
for i,a in enumerate(items, start=1):
if i % number_per_line == 0:
items[i-1] = str(i) + ".\t" + a + "\n"
else:
items[i-1] = str(i) + ".\t" + a + "\t"
def main(output_file, number = 80):
"""主函数"""
questions = []
answers = []
question_generator = [question_1, question_2, question_3]
for x in range(number):
which = random.choices([1,2,3], [0.2, 0.4, 0.4])[0] # 各类型题目概率
question, answer = question_generator[which-1]()
print( question)
questions.append(question)
answers.append(answer)
print("now write it")
write_it(questions, answers, output_file)
if __name__ == '__main__':
output_file = "out.txt"
main(output_file, number=800)