最近在做一个有意思的东西,里面有一块是生成四则运算给小朋友学习用的,基本已经都实现了,但是四则运算中有一部分算法我不是很满意,下面举例,希望能找到好的方向,谢谢各位参与。
要求:
A. 加减乘除 4 则运算,带正负号
B. 要能预先控制结果, 比如 A+B=C, 要求 100 以内,先 C = rand(1,100), A = rand(0, C), 这样就能算出 B 了
说明:
在简单模式下自然没有什么问题,我遇到的问题是在 A+(-B)*C/(-D+A), 在这种模式下只能大概控制结果的范围,无法做到精确控制
最新思路:
我准备下面考虑用填充法来做生成逻辑 比如
甲 A + B * C / D
乙 A*B + C/D
随机选择一个然后用数字去填充位置,貌似也不是很好
1
lygmqkl OP 希望能分享到合适的思路。
|
2
bearice 2015-10-30 09:29:05 +08:00 1
1 )随机生成一个自然数数作为运算结果
2 )随机生成一个运算符 3 )随机生成一个自然数作为运算符左参数,计算右参数 4 )对每个参数重复此过程,直到得到需要的算式长度为止 |
4
bearice 2015-10-30 09:37:10 +08:00
除法生成参数的时候就在 [1,9] 之间选择然后乘以结果
|
7
demo 2015-10-30 09:42:54 +08:00
算法这个东西还是需要一定的知识基础的
|
8
icedx 2015-10-30 09:48:25 +08:00 via Android
随便生成 然后用 eval 验证结果 只有四则运算的话
|
10
shiye515 2015-10-30 10:13:09 +08:00
首先,我假设楼主的意思是 参与运算的每个值 以及 每步运算的结果 都是不超过 100 的。那么,
只有一步的算式很好解决,如楼主举的加法的例子, 两步的运算就是把两个一步的算式嵌套下,(嵌套的意思是把参与运算的算式的一个值替换成一个算式) 同理 三步的算式就是 一个两步算式嵌套一个一步的算式。 |
11
Karblue 2015-10-30 13:58:44 +08:00 via Android
以前做过出题小程序。就随机生成。然后算一遍把期望的结果组留下就行了
|
12
fengyqf 2015-10-30 15:51:25 +08:00
随机生成吧,不过在成生后先计算一个结果,是不是在 100 以内,如果不是,就再生成一次。多让机器计算个四则,增加的时间消耗可以忽略
|
13
rogerchen 2015-10-30 16:01:43 +08:00
楼主这个问题和二十四点差不多,可以选定一个固定的算式 pattern ,枚举求解给定答案的所有算式。
举个例子,比如说 A op1 B op2 C op3 D op4 E = F 其中 F 给定, ABCDE 和 op1~op4 都可以在给定范围内遍历。 说实在的,这个方法虽然暴力,但是对处理小学生问题还手到擒来的,枚举几亿种可能对现代计算机不过洒洒水了。而且伸缩性也好,如果要缩减 operand 的数量,直接规定为*1 即可。所以楼主随便找个有 eval 算式的工具包,两分钟就搞定。 |
14
dnartz 2015-10-30 16:10:44 +08:00
可以考虑这样一个函数,返回一个以非叶子节点为运算符,叶子节点为数字(含正负号)的语法抽象树。
tree F(int c, int nOptr) -> operator = +-*/ 随机生成一个 int a, b; tree left, right; a = rand(1,c); switch operator b 为算符的右操作数,我们在这个 switch 里根据 operator 反推出 a // 如果我们满足继续拆分一个数字的条件,就继续拆分这个数字 // 拆分的条件就要依楼主的需求而确定了 // 比如只生成 n 个数字,那么我们可以引入一个参数 int nOptr // 我们用随机函数将 int nOptr 划分为 nOptr1 和 nOptr2 // 表示以 operator 为根节点的语法树左右两侧可以拥有的算符的数目,如果 nOptr1 或者 nOptr2 为 0 ,那就不拆分对应的数字 // 显然地,一个含有 n 个数字的算式,最多只可能有 n-1 个四则运算符(不是括号) // 所以对于一个含有 n 个数字,最后运算结果为 c 的算式,我们应该这样调用 F : F(c, n-1) nOptr1 = rand(1, nOptr) nOptr2 = nOptr - nOptr1 if nOptr1 > 0 left = f(a, nOptr1) else left = new leafNode(a) if nOptr2 > 0 right = f(b ,nOptr2) else right = new leafNode(b) 在生成语法树之后,我们也就可以生成算式了 在执行完这个算法之后,我们就可以通过这个语法树生成一个算式了 |
15
dnartz 2015-10-30 16:12:56 +08:00
|
16
akira 2015-10-30 18:55:53 +08:00
温习一遍波兰表达式,应该就足够了
|