我正在研究数学表达式简化器(相当基本,没有指数,日志,根,分数等),而且我主要使用它。在19项测试中,我使用了14项测试。对于剩下的5个,我在我的简化函数中写了多个其他语句,但它似乎没有改变。
下面是代码(复制并粘贴到解释器中,它可以正常工作)
//expression types
type Expression =
| X
| Y
| Const of float
| Neg of Expression
| Add of Expression * Expression
| Sub of Expression * Expression
| Mul of Expression * Expression
// formats string
let exprToString expr =
let rec recExprStr parens expr =
let lParen = if parens then "(" else ""
let rParen = if parens then ")" else ""
match expr with
| X -> "x"
| Y -> "y"
| Const n -> n.ToString()
| Neg e -> lParen + "-" + recExprStr true e + rParen
| Add (e1, e2) -> lParen + recExprStr true e1 + "+" + recExprStr true e2 + rParen
| Sub (e1, e2) -> lParen + recExprStr true e1 + "-" + recExprStr true e2 + rParen
| Mul (e1, e2) -> lParen + recExprStr true e1 + "*" + recExprStr true e2 + rParen
recExprStr false expr
//simplification function
let rec simplify expr =
match expr with
//addition
| Add(Const(ex1), Const(ex2)) -> Const(ex1 + ex2)
| Add(ex1, Const(0.)) -> ex1 |> simplify
| Add(Const(0.), ex1) -> ex1 |> simplify
| Add(Const(num), ex1) -> Add(ex1, Const(num)) |> simplify
| Add(ex1, Neg(ex2)) -> Sub(ex1, ex2) |> simplify
| Add(Neg(ex1), ex2) -> Sub(ex2, ex1) |> simplify
//subtraction
| Sub(Const(num1), Const(num2)) -> Const(num1 - num2)
| Sub(ex1, Const(0.)) -> ex1 |> simplify
| Sub(Const(0.), ex1) -> Neg(ex1) |> simplify
//multiplication
| Mul(Const(num1), Const(num2)) -> Const(num1 * num2)
| Mul(ex1, Const(1.)) -> ex1 |> simplify
| Mul(Const(1.), ex1) -> ex1 |> simplify
| Mul(ex1, Const(0.)) -> Const(0.)
| Mul(Const(0.), ex1) -> Const(0.)
| Mul(ex1, Const(num1)) -> Mul(Const(num1), ex1) |> simplify
| Mul(Neg(ex1), ex2) -> Neg(Mul(ex1, ex2)) |> simplify
| Mul(ex1, Neg(ex2)) -> Neg(Mul(ex1, ex2)) |> simplify
//negation involving a number
| Neg(Const(0.)) -> Const(0.)
| Neg(Neg(ex1)) -> ex1 |> simplify
| _ -> expr
//Tests
printfn "---Provided Tests---"
let t1 = Add (Const 5.0, Const 3.0)
let t2 = Sub (Const 5.0, Const 3.0)
let t3 = Mul (Const 5.0, Const 3.0)
let t4 = Neg (Const 4.0)
let t5 = Neg (Const -9.0)
let t6 = Add (X, Const 0.0)
let t7 = Add (Const 0.0, Y)
let t8 = Sub (X, Const 0.0)
let t9 = Sub (Const 0.0, Y)
let t10 = Sub (Y, Y)
let t11 = Mul (X, Const 0.0)
let t12 = Mul (Const 0.0, Y)
let t13 = Mul (X, Const 1.0)
let t14 = Mul (Const 1.0, Y)
let t15 = Neg (Neg X)
let t16 = Sub (Mul (Const 1.0, X), Add (X, Const 0.0))
let t17 = Add (Mul (Const 4.0, Const 3.0), Sub (Const 11.0, Const 5.0))
let t18 = Sub (Sub (Add (X, Const 1.0), Add (X, Const 1.0)), Add (Y, X))
let t19 = Sub (Const 0.0, Neg (Mul (Const 1.0, X)))
//Output goes here!
//5 + 3 = 0
printfn "t1 Correct: 8\t\tActual: %s" (exprToString (simplify t1))
//5-3 = 2
printfn "t2 Correct: 2\t\tActual: %s" (exprToString (simplify t2))
//5 * 3 = 15
printfn "t3 Correct: 15\t\tActual: %s" (exprToString (simplify t3))
//-(4) = -4
printfn "t4 Correct: -4\t\tActual: %s" (exprToString (simplify t4))
//-(-9) = 9
printfn "t5 Correct: 9\t\tActual: %s" (exprToString (simplify t5))
//x + 0 = x
printfn "t6 Correct: x\t\tActual: %s" (exprToString (simplify t6))
//0 + y = y
printfn "t7 Correct: y\t\tActual: %s" (exprToString (simplify t7))
//x - 0 = x
printfn "t8 Correct: x\t\tActual: %s" (exprToString (simplify t8))
//0 - y = -y
printfn "t9 Correct: -y\t\tActual: %s" (exprToString (simplify t9))
//y - y = 0
printfn "t10 Correct: 0\t\tActual: %s" (exprToString (simplify t10))
//x * 0 = 0
printfn "t11 Correct: 0\t\tActual: %s" (exprToString (simplify t11))
//0 * y = 0
printfn "t12 Correct: 0\t\tActual: %s" (exprToString (simplify t12))
//x * 1 = x
printfn "t13 Correct: x\t\tActual: %s" (exprToString (simplify t13))
//1 * y = y
printfn "t14 Correct: y\t\tActual: %s" (exprToString (simplify t14))
//-(-x) = x
printfn "t15 Correct: x\t\tActual: %s" (exprToString (simplify t15))
// (1 * x) - (x + 0) = 0
printfn "t16 Correct: 0\t\tActual: %s" (exprToString (simplify t16))
//(4 * 3) + (11 - 5) = 18
printfn "t17 Correct: 18\t\tActual: %s" (exprToString (simplify t17))
// ((x + 1) - (x + 1)) - (y+x) = -y -x
printfn "t18 Correct: -y -x\t\tActual: %s" (exprToString (simplify t18))
// 0 - (-(1 * x)) = x
printfn "t19 Correct: x\t\tActual: %s" (exprToString (simplify t19))
// (x + 1) * (-2y + x)
程序的输出如下,我已经标记了6个失败的测试(正确的是正确的答案,实际是我正在返回)
t1 Correct: 8 Actual: 8
t2 Correct: 2 Actual: 2
t3 Correct: 15 Actual: 15
t4 Correct: -4 Actual: -4
t5 Correct: 9 Actual: --9 //FAILS
t6 Correct: x Actual: x
t7 Correct: y Actual: y
t8 Correct: x Actual: x
t9 Correct: -y Actual: -y
t10 Correct: 0 Actual: y-y //FAILS
t11 Correct: 0 Actual: 0
t12 Correct: 0 Actual: 0
t13 Correct: x Actual: x
t14 Correct: y Actual: y
t15 Correct: x Actual: x
t16 Correct: 0 Actual: (1*x)-(x+0) //FAILS
t17 Correct: 18 Actual: (4*3)+(11-5) //FAILS
t18 Correct: -(y + x) Actual: ((x+1)-(x+1))-(y+x) //FAILS
t19 Correct: x Actual: x
我对如何解决最后的4(16,17,18)感到有点困惑但在我看来,我对#5和#10应该有所作为。
对于测试5,我包括| Neg(Neg(ex1)) -> ex1 |> simplify
,我认为这会让我的双重否定但不会。
对于测试10,我认为像| Sub(ex1, ex2) -> (ex1 - ex2)
这样的东西会起作用,但事实证明它甚至不是有效的语法。
我已经查看了大约六个左右的简化资源,甚至复制和粘贴他们的一些工作我的测试仍然失败。它知道我必须错过一两个案例,但是我拉着我的头发试图弄清楚我可能遗漏了什么!我非常感谢任何输入!
(原帖有一个测试20,我已经将其删除以用于简化答案。鉴于我目前的代码,我意识到我无法简化它)
答案 0 :(得分:3)
5:Neg(Const -9)
没有得到简化。这不是消极的负面影响。您需要使用规则Neg(Const x) -> Const(-x)
来替换Neg(Const 0.)
。{/ p>
10:Sub(x,y) when y = x -> Const(0)
Sub(x,y) -> let x',y' = simplify x, simplify y
然后match x',y' with....
17:16解决方案可以解决这个问题。
18:10和16的解决方案可以解决这个问题。
此外,我无法抗拒建议let t = [Add (Const 5.0, Const 3.0); Sub (Const 5.0, Const 3.0)...]
然后t |> List.iteri ...
。
我正在使用一个特殊的代数简化器,它可以做得很好,但是想创建一个更严肃的代数。如果有人认真对待这个问题,请告诉我。