-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChapter_06_ex_3.fs
More file actions
158 lines (141 loc) · 10.2 KB
/
Chapter_06_ex_3.fs
File metadata and controls
158 lines (141 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
module Chapter_06_ex_3
#if INTERACTIVE
#r "packages/Unquote.2.2.2/lib/net40/unquote.dll"
#r "packages/NUnit.2.6.2/lib/nunit.framework.dll"
#endif
open System
open System.Globalization
open NUnit.Framework
open Swensen.Unquote
// 6.3 - better toString
type Fexpr = | Const of float
| X // What is this doing??
| Add of Fexpr * Fexpr
| Sub of Fexpr * Fexpr
| Mul of Fexpr * Fexpr
| Div of Fexpr * Fexpr
| Sin of Fexpr
| Cos of Fexpr
| Log of Fexpr
| Exp of Fexpr
// The original toString
let rec toString = function
| Const x -> string x
| X -> "x"
| Add(fe1,fe2) -> "(" + (toString fe1) + ")"
+ " + " + "(" + (toString fe2) + ")"
| Sub(fe1,fe2) -> "(" + (toString fe1) + ")"
+ " - " + "(" + (toString fe2) + ")"
| Mul(fe1,fe2) -> "(" + (toString fe1) + ")"
+ " * " + "(" + (toString fe2) + ")"
| Div(fe1,fe2) -> "(" + (toString fe1) + ")"
+ " / " + "(" + (toString fe2) + ")"
| Sin fe -> "(sin " + (toString fe) + ")"
| Cos fe -> "(cos " + (toString fe) + ")"
| Log fe -> "(log " + (toString fe) + ")"
| Exp fe -> "(exp " + (toString fe) + ")";;
// It takes a LOT of patterns to complete this! (And a lot of tests to verify...)
// It would be possible to reduce the amount of patterns by using when expressions
// but I actually prefer patterns. I think I have all the permutations covered ;9
let rec betterToString = function
| Const value -> String.Format(CultureInfo.InvariantCulture, "{0:0.0######}", value)
| X -> "x"
| Add((Mul(_,_) as mul1), (Mul(_,_) as mul2)) -> "(" + (betterToString mul1) + ")"
+ " + " + "(" + (betterToString mul2) + ")"
| Add((Div(_,_) as div1), (Div(_,_) as div2)) -> "(" + (betterToString div1) + ")"
+ " + " + "(" + (betterToString div2) + ")"
| Add((Mul(_,_) as mul), (Div(_,_) as div)) -> "(" + (betterToString mul) + ")"
+ " + " + "(" + (betterToString div) + ")"
| Add((Div(_,_) as div), (Mul(_,_) as mul)) -> "(" + (betterToString div) + ")"
+ " + " + "(" + (betterToString mul) + ")"
| Add((Mul(_,_) as mul), fe2) -> "(" + (betterToString mul) + ")"
+ " + " + (betterToString fe2)
| Add((Div(_,_) as div), fe2) -> "(" + (betterToString div) + ")"
+ " + " + (betterToString fe2)
| Add(fe1, (Mul(_,_) as mul)) -> (betterToString fe1)
+ " + " + "(" + (betterToString mul) + ")"
| Add(fe1, (Div(_,_) as div)) -> (betterToString fe1)
+ " + " + "(" + (betterToString div) + ")"
| Add(fe1,fe2) -> (betterToString fe1) + " + " + (betterToString fe2)
| Sub((Mul(_,_) as mul1), (Mul(_,_) as mul2)) -> "(" + (betterToString mul1) + ")"
+ " - " + "(" + (betterToString mul2) + ")"
| Sub((Div(_,_) as div1), (Div(_,_) as div2)) -> "(" + (betterToString div1) + ")"
+ " - " + "(" + (betterToString div2) + ")"
| Sub((Mul(_,_) as mul), (Div(_,_) as div)) -> "(" + (betterToString mul) + ")"
+ " - " + "(" + (betterToString div) + ")"
| Sub((Div(_,_) as div), (Mul(_,_) as mul)) -> "(" + (betterToString div) + ")"
+ " - " + "(" + (betterToString mul) + ")"
| Sub((Mul(_,_) as mul), fe2) -> "(" + (betterToString mul) + ")"
+ " - " + (betterToString fe2)
| Sub((Div(_,_) as div), fe2) -> "(" + (betterToString div) + ")"
+ " - " + (betterToString fe2)
| Sub(fe1, (Mul(_,_) as mul)) -> (betterToString fe1)
+ " - " + "(" + (betterToString mul) + ")"
| Sub(fe1, (Div(_,_) as div)) -> (betterToString fe1)
+ " - " + "(" + (betterToString div) + ")"
| Sub(fe1,fe2) -> (betterToString fe1) + " - " + (betterToString fe2)
| Mul((Add(_, _) as add1), (Add(_, _) as add2)) -> "(" + (betterToString add1) + ")"
+ " * " + "(" + (betterToString add2) + ")"
| Mul((Sub(_, _) as sub1), (Sub(_, _) as sub2)) -> "(" + (betterToString sub1) + ")"
+ " * " + "(" + (betterToString sub2) + ")"
| Mul((Add(_, _) as add), (Sub(_, _) as sub)) -> "(" + (betterToString add) + ")"
+ " * " + "(" + (betterToString sub) + ")"
| Mul((Sub(_, _) as sub), (Add(_, _) as add)) -> "(" + (betterToString sub) + ")"
+ " * " + "(" + (betterToString add) + ")"
| Mul(Add(_, _) as add, fe2) -> "(" + (betterToString add) + ")"
+ " * " + (betterToString fe2)
| Mul(Sub(_, _) as sub, fe2) -> "(" + (betterToString sub) + ")"
+ " * " + (betterToString fe2)
| Mul(fe1, (Add(_, _) as add)) -> (betterToString fe1)
+ " * " + "(" + (betterToString add) + ")"
| Mul(fe1, (Sub(_, _) as sub)) -> (betterToString fe1)
+ " * " + "(" + (betterToString sub) + ")"
| Mul(fe1,fe2) -> "(" + (betterToString fe1) + ")"
+ " * " + "(" + (betterToString fe2) + ")"
| Div((Add(_, _) as add1), (Add(_, _) as add2)) -> "(" + (betterToString add1) + ")"
+ " / " + "(" + (betterToString add2) + ")"
| Div((Sub(_, _) as sub1), (Sub(_, _) as sub2)) -> "(" + (betterToString sub1) + ")"
+ " / " + "(" + (betterToString sub2) + ")"
| Div((Add(_, _) as add), (Sub(_, _) as sub)) -> "(" + (betterToString add) + ")"
+ " / " + "(" + (betterToString sub) + ")"
| Div((Sub(_, _) as sub), (Add(_, _) as add)) -> "(" + (betterToString sub) + ")"
+ " / " + "(" + (betterToString add) + ")"
| Div(Add(_, _) as add, fe2) -> "(" + (betterToString add) + ")"
+ " / " + (betterToString fe2)
| Div(Sub(_, _) as sub, fe2) -> "(" + (betterToString sub) + ")"
+ " / " + (betterToString fe2)
| Div(fe1, (Add(_, _) as add)) -> (betterToString fe1)
+ " / " + "(" + (betterToString add) + ")"
| Div(fe1, (Sub(_, _) as sub)) -> (betterToString fe1)
+ " / " + "(" + (betterToString sub) + ")"
| Div(fe1,fe2) -> "(" + (betterToString fe1) + ")"
+ " / " + "(" + (betterToString fe2) + ")"
| Sin(Const(_) as c) -> "sin " + (betterToString c)
| Sin(X as x) -> "sin " + (betterToString x)
| Sin fe -> "sin" + "(" + (betterToString fe) + ")"
| Cos(Const(_) as c) -> "cos " + (betterToString c)
| Cos(X as x) -> "cos " + (betterToString x)
| Cos fe -> "cos" + "(" + (betterToString fe) + ")"
| Log(Const(_) as c) -> "log " + (betterToString c)
| Log(X as x) -> "log " + (betterToString x)
| Log fe -> "log" + "(" + (betterToString fe) + ")"
| Exp(Const(_) as c) -> "exp " + (betterToString c)
| Exp(X as x) -> "exp " + (betterToString x)
| Exp fe -> "exp" + "(" + (betterToString fe) + ")"
[<TestFixture>]
type ``Chapter 06 exercise 3 Tests``() =
[<Test>]
member x.``6.3 toString without uncessesary parenthesis``() =
test <@ betterToString (Mul(Add(Const(2.0), Const(3.0)), Sub(Const(4.0), Const(5.0))))
= "(2.0 + 3.0) * (4.0 - 5.0)" @>
test <@ betterToString (Mul(Sub(Const(2.0), Const(3.0)), Add(Const(4.0), Const(5.0))))
= "(2.0 - 3.0) * (4.0 + 5.0)" @>
test <@ betterToString (Mul(Sin(Const(3.0)), Sub(Const(4.0), Const(5.0))))
= "sin 3.0 * (4.0 - 5.0)" @>
test <@ betterToString (Mul(Sub(Const(2.0), Const(3.0)), Sin(Const(4.0))))
= "(2.0 - 3.0) * sin 4.0" @>
test <@ betterToString (Div(Add(Const(2.0), Const(3.0)), Sub(Const(4.0), Const(5.0))))
= "(2.0 + 3.0) / (4.0 - 5.0)" @>
test <@ betterToString (Div(Sub(Const(2.0), Const(3.0)), Add(Const(4.0), Const(5.0))))
= "(2.0 - 3.0) / (4.0 + 5.0)" @>
test <@ betterToString (Sin(Add(Const(2.0), Const(3.0)))) = "sin(2.0 + 3.0)" @>