latex_eval 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d0562d9054359a1d2a318e8dec10943b3a56bb8a
4
+ data.tar.gz: a1ff0986f7fd46f1c6a8adf4a07656a533b19ece
5
+ SHA512:
6
+ metadata.gz: 63370a4e0a0f39c47de118b18d695c77b0e10fb62ad38d7507ab0eb2c1991f52c086965826be26c327f8a95cae88b82c35a2a8552dde0fbf8f13d84d8c6d0702
7
+ data.tar.gz: d4d0b786b24b969ea3adfc9cba2a64c3d632ba4b7db8de44326608e676fff90fc4a5d591f7dd63b067cf935da4aa20120d22b2ae3fd2944b50ad9d8ad7157279
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # latex\_eval
2
+
3
+ This gem can be used to safely evaluate simple latex expressions.
4
+
5
+ For example, if you want to evaluate `\frac{\xi}{2}+3` where `\xi = 3` you can do
6
+
7
+ LatexEval.eval('\frac{\xi}{2}+3', {xi: 3})
8
+
9
+ However, if you are going to be evaluating the expression many times, it is best to save the postfix notation first.
10
+
11
+ postfix = LatexEval.postfix_notation('\frac{\xi}{2}+3')
12
+ LatexEval::PostfixNotation.eval(postfix, {xi: 3})
13
+
14
+ This gem is made up of 3 classes. `Latex`, `Equation`, and `PostfixNotation`. I will explain their uses.
15
+
16
+ ## Latex
17
+
18
+ The latex class is used to convert your latex into an equation. For example,
19
+
20
+ LatexEval::Latex.new('\frac{\xi}{2}+3').equation
21
+
22
+ will output `((xi)/(2)+3)`.
23
+
24
+ Currently, the `equation` method for the `Latex` class supports the following latex expressions:
25
+
26
+ - capital and lowercase Greek letters (`\alpha`, `\Beta`, etc.)
27
+ - single letter variables (`a`, `b`, ..., `z`)
28
+ - fractions in the form of `\frac{}{}` and `\dfrac{}{}`
29
+ - roots in the form `\sqrt{}` and `\sqrt[]{}`
30
+ - binary operators
31
+ - multiplication (\*, `\cdot`, `\times`)
32
+ - division(/)
33
+ - powers (^)
34
+ - modulus (%)
35
+ - addition (+)
36
+ - subtraction (-)
37
+ - unary operators
38
+ - positive (+)
39
+ - negative (-)
40
+
41
+ ## Equation
42
+
43
+ The equation class is used to convert your equations into postfix notation. For example,
44
+
45
+ LatexEval::Equation.new('((xi)/(2)+3)').postfix_notation
46
+
47
+ will output `[3, :xi, 2, :divide, :add]`.
48
+
49
+ Currently, the `postfix_notation` method for the `Equation` class can interpret
50
+
51
+ - brackets
52
+ - binary operators
53
+ - multiplication (\*)
54
+ - division(/)
55
+ - powers (^)
56
+ - modulus (%)
57
+ - addition (+)
58
+ - subtraction (-)
59
+ - unary operators
60
+ - positive (+)
61
+ - negative (-)
62
+
63
+ and will adhere to the generally accepted order of operations.
64
+
65
+ ## PostfixNotation
66
+
67
+ The postfix equation class is used to safely evaluate postfix notation. For example,
68
+
69
+ LatexEval::PostfixNotation.new([3, :xi, 2, :divide, :add]).eval({xi: 3})
70
+
71
+ will output `4.5`.
72
+
73
+ The `eval` method accepts one argument, which is a hash of variable values.
74
+
75
+ Currently, the `eval` method for the `PostfixNotation` class can interpret
76
+
77
+ - binary operators
78
+ - :multiply
79
+ - :divide
80
+ - :power
81
+ - :mod
82
+ - :add
83
+ - :subtract
84
+ - unary operators
85
+ - :positive
86
+ - :negative
data/lib/latex_eval.rb ADDED
@@ -0,0 +1,21 @@
1
+ require_relative "./latex_eval/equation.rb"
2
+ require_relative "./latex_eval/postfix_notation.rb"
3
+ require_relative "./latex_eval/latex.rb"
4
+
5
+ module LatexEval
6
+ class << self
7
+
8
+ def eval(latex, subs = {})
9
+ parsed_latex = LatexEval::Latex.new(latex).equation
10
+ parsed_notation = LatexEval::Equation.new(parsed_latex).postfix_notation
11
+ eval_latex = LatexEval::PostfixNotation.new(parsed_notation)
12
+
13
+ return eval_latex.eval(subs)
14
+ end
15
+
16
+ def postfix_notation(latex)
17
+ equation = LatexEval::Latex.new(latex).equation
18
+ return LatexEval::Equation.new(equation).postfix_notation
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,104 @@
1
+ module LatexEval
2
+ class Equation
3
+
4
+ attr_reader :binary_key, :equation, :unary_key
5
+
6
+ def initialize(equation)
7
+ @equation = equation
8
+ @binary_key = {
9
+ "+" => {
10
+ symbol: :add,
11
+ priority: 0,
12
+ right_priority: false
13
+ },
14
+ "-" => {
15
+ symbol: :subtract,
16
+ priority: 0,
17
+ right_priority: false
18
+ },
19
+ "*" => {
20
+ symbol: :multiply,
21
+ priority: 1,
22
+ right_priority: false
23
+ },
24
+ "/" => {
25
+ symbol: :divide,
26
+ priority: 1,
27
+ right_priority: false
28
+ },
29
+ "%" => {
30
+ symbol: :mod,
31
+ priority: 1,
32
+ right_priority: false
33
+ },
34
+ "^" => {
35
+ symbol: :power,
36
+ priority: 2,
37
+ right_priority: true
38
+ }
39
+ }
40
+ @unary_key = {
41
+ "-" => {
42
+ symbol: :negative,
43
+ },
44
+ "+" => {
45
+ symbol: :positive,
46
+ },
47
+ }
48
+ end
49
+
50
+ def postfix_notation
51
+ out = []
52
+ bank = []
53
+ bracket = []
54
+ unary = []
55
+
56
+ # start with an assumed array
57
+ bank.push []
58
+ bracket.push []
59
+ unary.push []
60
+
61
+ equation.gsub(" ", "").split(/([%\)\(\^*+-\/])/).each do |value|
62
+ if value != ""
63
+ if value == "("
64
+ bank.push []
65
+ bracket.push []
66
+ unary.push []
67
+ elsif value == ")"
68
+ last = bracket.pop()
69
+ bracket.last.concat last
70
+ bracket.last.concat bank.pop().reverse.map { |e| binary_key[e][:symbol] }
71
+ bracket.last.concat unary.pop().reverse.map { |e| unary_key[e][:symbol] }
72
+ elsif unary_key.has_key? value and (bracket.last.empty? || bracket.last.length == bank.last.length)
73
+ unary.last.push value
74
+ elsif binary_key.has_key? value
75
+ num_popped = 0
76
+ bank.last.reverse_each do |b|
77
+ if (binary_key[b][:right_priority] ? binary_key[b][:priority] > binary_key[value][:priority] : binary_key[b][:priority] >= binary_key[value][:priority])
78
+ num_popped += 1
79
+ else
80
+ break
81
+ end
82
+ end
83
+ bracket.last.concat unary.pop().reverse.map { |e| unary_key[e][:symbol] }
84
+ unary.push []
85
+ bracket.last.concat bank.last.pop(num_popped).reverse.map { |e| binary_key[e][:symbol] }
86
+ bank.last.push value
87
+ else
88
+ if /[a-zA-Z]+/.match(value)
89
+ bracket.last.push value.to_sym
90
+ else
91
+ bracket.last.push value.to_f
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ out.concat bracket.pop()
98
+ out.concat unary.pop().reverse.map { |e| unary_key[e][:symbol] }
99
+ out.concat bank.pop().reverse.map { |e| binary_key[e][:symbol] }
100
+
101
+ return out
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,128 @@
1
+ module LatexEval
2
+ class Latex
3
+ attr_reader :latex, :greek_letters
4
+
5
+ def initialize(latex)
6
+ @latex = latex
7
+ @greek_letters = [
8
+ 'Alpha',
9
+ 'alpha',
10
+ 'Beta',
11
+ 'beta',
12
+ 'Gamma',
13
+ 'gamma',
14
+ 'Delta',
15
+ 'delta',
16
+ 'Epsilon',
17
+ 'epsilon',
18
+ 'varepsilon',
19
+ 'Zeta',
20
+ 'zeta',
21
+ 'Eta',
22
+ 'eta',
23
+ 'Theta',
24
+ 'theta',
25
+ 'vartheta',
26
+ 'Iota',
27
+ 'iota',
28
+ 'Kappa',
29
+ 'kappa',
30
+ 'varkappa',
31
+ 'Lambda',
32
+ 'lambda',
33
+ 'Mu',
34
+ 'mu',
35
+ 'Nu',
36
+ 'nu',
37
+ 'Xi',
38
+ 'xi',
39
+ 'Omicron',
40
+ 'omicron',
41
+ 'Pi',
42
+ 'pi',
43
+ 'varpi',
44
+ 'Rho',
45
+ 'rho',
46
+ 'varrho',
47
+ 'Sigma',
48
+ 'sigma',
49
+ 'varsigma',
50
+ 'Tau',
51
+ 'tau',
52
+ 'Upsilon',
53
+ 'upsilon',
54
+ 'Phi',
55
+ 'phi',
56
+ 'varphi',
57
+ 'Chi',
58
+ 'chi',
59
+ 'Psi',
60
+ 'psi',
61
+ 'Omega',
62
+ 'omega',
63
+ ]
64
+ end
65
+
66
+ def equation
67
+ parsed = latex
68
+
69
+ parsed.gsub!(/\\left/, "")
70
+ parsed.gsub!(/\\right/, "")
71
+
72
+ # fractions
73
+ regex = /\\d?frac{(.*)}{(.*)}/
74
+ while parsed.match(regex)
75
+ parsed.gsub!(regex, '((\1)/(\2))')
76
+ end
77
+
78
+ # sqrt
79
+ regex = /\\sqrt{(.*)}/
80
+ while parsed.match(regex)
81
+ parsed.gsub!(regex, '((\1)^(1/2))')
82
+ end
83
+
84
+ # nth root
85
+ regex = /\\sqrt(\[?(.*)(?=\])\]?)?{(.*)}/
86
+ while parsed.match(regex)
87
+ parsed.gsub!(regex, '((\3)^(1/(\2)))')
88
+ end
89
+
90
+ # \cdot and \times should be *
91
+ parsed.gsub!(/\\cdot/, "*")
92
+ parsed.gsub!(/\\times/, "*")
93
+
94
+ # remove remaining curly brackets
95
+ parsed.gsub!(/{/, "(")
96
+ parsed.gsub!(/}/, ")")
97
+
98
+ # cleanup variable names and multiplication
99
+ greek_letters.each do |letter|
100
+ parsed.gsub!(/(\\#{letter})/, ' \1 ')
101
+ end
102
+
103
+ # cleans up xyz to x*y*z
104
+ regex = /((?<!\\)\b)([0-9]?[A-Za-z])([A-Za-z])/
105
+ while parsed.match(regex)
106
+ parsed.gsub!(regex, '\2*\3')
107
+ end
108
+
109
+ parsed.gsub!(/([0-9])\s+\\([A-Za-z])/, '\1*\2')
110
+ parsed.gsub!(/([0-9])\s*?([A-Za-z])/, '\1*\2')
111
+
112
+ parsed.gsub!(/([A-Za-z])\s+\\([A-Za-z])/, '\1*\2')
113
+ parsed.gsub!(/([A-Za-z])\s+([A-Za-z])/, '\1*\2')
114
+
115
+ parsed.gsub!(/([A-Za-z])\s+([0-9])/, '\1*\2')
116
+ parsed.gsub!(/([A-Za-z])([0-9])/, '\1*\2')
117
+
118
+ parsed.gsub!(/(\))(\()/, '\1*\2')
119
+
120
+ parsed.gsub!(/\\/, "")
121
+
122
+ # cleanup spaces
123
+ parsed.gsub!(" ", "")
124
+
125
+ return parsed
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,61 @@
1
+ module LatexEval
2
+ class PostfixNotation
3
+ attr_reader :notation, :operations
4
+
5
+ def initialize(notation)
6
+ @notation = notation
7
+ @operations = {
8
+ add: {
9
+ args: 2,
10
+ operation: ->(a,b) { a + b },
11
+ },
12
+ subtract: {
13
+ args: 2,
14
+ operation: ->(a,b) { a - b },
15
+ },
16
+ multiply: {
17
+ args: 2,
18
+ operation: ->(a,b) { a * b },
19
+ },
20
+ divide: {
21
+ args: 2,
22
+ operation: ->(a,b) { a / b },
23
+ },
24
+ power: {
25
+ args: 2,
26
+ operation: ->(a,b) { a ** b },
27
+ },
28
+ mod: {
29
+ args: 2,
30
+ operation: ->(a,b) { a % b },
31
+ },
32
+ negative: {
33
+ args: 1,
34
+ operation: ->(a) { -a },
35
+ },
36
+ positive: {
37
+ args: 1,
38
+ operation: ->(a) { +a },
39
+ },
40
+ }
41
+ end
42
+
43
+ def eval(subs = {})
44
+ stack = []
45
+
46
+ notation.each do |elem|
47
+ if elem.is_a? Symbol
48
+ if operations.has_key? elem
49
+ stack.push operations[elem][:operation].call(*stack.pop(operations[elem][:args])).to_f
50
+ else
51
+ stack.push subs[elem].to_f
52
+ end
53
+ else
54
+ stack.push elem.to_f
55
+ end
56
+ end
57
+
58
+ return stack.first
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,169 @@
1
+ require 'minitest/autorun'
2
+ require_relative './../lib/latex_eval.rb'
3
+
4
+ class TestEquation < Minitest::Test
5
+ def test_that_parser_parses_addition
6
+ equation = "1 + 2"
7
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :add]
8
+ end
9
+
10
+ def test_that_parser_parses_subtraction
11
+ equation = "1 - 2"
12
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :subtract]
13
+ end
14
+
15
+ def test_that_parser_parses_multiplication
16
+ equation = "1 * 2"
17
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :multiply]
18
+ end
19
+
20
+ def test_that_parser_parses_division
21
+ equation = "1 / 2"
22
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :divide]
23
+ end
24
+
25
+ def test_that_parser_parses_powers
26
+ equation = "1 ^ 2"
27
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :power]
28
+ end
29
+
30
+ def test_that_parser_respects_brackets
31
+ equation = "(1+2)^3"
32
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :add, 3, :power]
33
+ end
34
+
35
+ def test_that_parser_respects_nested_brackets
36
+ equation = "(1+(2-4))^3"
37
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 4, :subtract, :add, 3, :power]
38
+ end
39
+
40
+ def test_that_parser_respects_separate_brackets
41
+ equation = "(1+(2-4))^(3 * 2)"
42
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 4, :subtract, :add, 3, 2, :multiply, :power]
43
+ end
44
+
45
+ def test_that_parser_respects_separate_brackets_v2
46
+ equation = "(1-(2-4))^(3 * 2)"
47
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 4, :subtract, :subtract, 3, 2, :multiply, :power]
48
+ end
49
+
50
+ def test_that_parser_disregards_spaces
51
+ equation = "( 1 + 2 ) ^ 3"
52
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :add, 3, :power]
53
+ end
54
+
55
+ def test_that_parser_recognizes_single_letter_variables
56
+ equation = "x + y + z"
57
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [:x, :y, :add, :z, :add]
58
+ end
59
+
60
+ def test_that_parser_recognizes_multi_letter_variables
61
+ equation = "alpha + beta + gamma"
62
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [:alpha, :beta, :add, :gamma, :add]
63
+ end
64
+
65
+ def test_that_parser_evaluates_multiply_divide_in_order_of_appearance
66
+ equation = "1 * 2 / 3"
67
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :multiply, 3, :divide]
68
+ end
69
+
70
+ def test_that_parser_evaluates_add_subtract_in_order_of_appearance
71
+ equation = "1 + 2 - 3"
72
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, :add, 3, :subtract]
73
+ end
74
+
75
+ def test_that_powers_are_given_proper_priority
76
+ equation = "3 ^ 2 ^ 2"
77
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [3, 2, 2, :power, :power]
78
+ end
79
+
80
+ def test_that_parser_multiplication_priority_over_addition
81
+ equation = "1 + 2 * 3"
82
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :multiply, :add]
83
+ end
84
+
85
+ def test_that_parser_multiplication_priority_over_subtraction
86
+ equation = "1 - 2 * 3"
87
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :multiply, :subtract]
88
+ end
89
+
90
+ def test_that_parser_division_priority_over_addition
91
+ equation = "1 + 2 / 3"
92
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :divide, :add]
93
+ end
94
+
95
+ def test_that_parser_division_priority_over_subtraction
96
+ equation = "1 - 2 / 3"
97
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :divide, :subtract]
98
+ end
99
+
100
+ def test_that_parser_power_priority_over_addition
101
+ equation = "1 + 2 ^ 3"
102
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :power, :add]
103
+ end
104
+
105
+ def test_that_parser_power_priority_over_subtraction
106
+ equation = "1 - 2 ^ 3"
107
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :power, :subtract]
108
+ end
109
+
110
+ def test_that_parser_power_priority_over_multiplication
111
+ equation = "1 * 2 ^ 3"
112
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :power, :multiply]
113
+ end
114
+
115
+ def test_that_parser_power_priority_over_division
116
+ equation = "1 / 2 ^ 3"
117
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :power, :divide]
118
+ end
119
+
120
+ def test_that_parser_mod_priority_over_addition
121
+ equation = "1 + 2 % 3"
122
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :mod, :add]
123
+ end
124
+
125
+ def test_that_parser_mod_priority_over_subtraction
126
+ equation = "1 - 2 % 3"
127
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [1, 2, 3, :mod, :subtract]
128
+ end
129
+
130
+ def test_that_negative_works
131
+ equation = "- 2"
132
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [2, :negative]
133
+ end
134
+
135
+ def test_that_positive_works
136
+ equation = "+ 2"
137
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [2, :positive]
138
+ end
139
+
140
+ def test_that_negative_works_inside_brackets
141
+ equation = "(-2)"
142
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [2, :negative]
143
+ end
144
+
145
+ def test_that_negative_works_outside_brackets
146
+ equation = "-(2)"
147
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [2, :negative]
148
+ end
149
+
150
+ def test_that_negative_works_with_others
151
+ equation = "-2+3"
152
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [2, :negative, 3, :add]
153
+ end
154
+
155
+ def test_that_negative_works_with_multiple_negatives
156
+ equation = "--2"
157
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [2, :negative, :negative]
158
+ end
159
+
160
+ def test_that_negative_works_with_multiplication_normal
161
+ equation = "2 * - 2"
162
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [2, 2, :negative, :multiply]
163
+ end
164
+
165
+ def test_that_negative_works_with_multiple_negatives_2
166
+ equation = "2^(-2)"
167
+ assert_equal LatexEval::Equation.new(equation).postfix_notation, [2, 2, :negative, :power]
168
+ end
169
+ end
@@ -0,0 +1,14 @@
1
+ require 'minitest/autorun'
2
+ require_relative './../lib/latex_eval.rb'
3
+
4
+ class TestLatexEval < Minitest::Test
5
+ def test_it_all
6
+ latex = '\frac{1}{2}\cdot3\xi+4'
7
+ assert_equal LatexEval.eval(latex, {xi: 2}), 7
8
+ end
9
+
10
+ def test_postfix_notation
11
+ latex = '1+3*2'
12
+ assert_equal LatexEval.postfix_notation(latex), [1, 3, 2, :multiply, :add]
13
+ end
14
+ end
@@ -0,0 +1,134 @@
1
+ require 'minitest/autorun'
2
+ require_relative './../lib/latex_eval.rb'
3
+
4
+ class TestLatex < Minitest::Test
5
+ def test_that_latex_parser_parses_fractions
6
+ latex = '\frac{1}{2}'
7
+ assert_equal LatexEval::Latex.new(latex).equation, '((1)/(2))'
8
+ end
9
+
10
+ def test_that_latex_parser_parses_fractions_recursively
11
+ latex = '\frac{\frac{3}{4}}{2}'
12
+ assert_equal LatexEval::Latex.new(latex).equation, '((((3)/(4)))/(2))'
13
+ end
14
+
15
+ def test_that_latex_parser_parses_dfractions
16
+ latex = '\dfrac{1}{2}'
17
+ assert_equal LatexEval::Latex.new(latex).equation, '((1)/(2))'
18
+ end
19
+
20
+ def test_that_latex_parser_parses_dfractions_recursively
21
+ latex = '\dfrac{\dfrac{3}{4}}{2}'
22
+ assert_equal LatexEval::Latex.new(latex).equation, '((((3)/(4)))/(2))'
23
+ end
24
+
25
+ def test_that_latex_parser_parses_cdot
26
+ latex = '1\cdot2'
27
+ assert_equal LatexEval::Latex.new(latex).equation, '1*2'
28
+ end
29
+
30
+ def test_that_latex_parser_parses_times
31
+ latex = '1\times2'
32
+ assert_equal LatexEval::Latex.new(latex).equation, '1*2'
33
+ end
34
+
35
+ def test_that_latex_parser_parses_powers
36
+ latex = '1^{23}'
37
+ assert_equal LatexEval::Latex.new(latex).equation, '1^(23)'
38
+ end
39
+
40
+ def test_that_latex_parser_parses_variable_names
41
+ latex = '\xi'
42
+ assert_equal LatexEval::Latex.new(latex).equation, 'xi'
43
+ end
44
+
45
+ def test_that_latex_parser_adds_missing_multiplication_before_variable
46
+ latex = '2\xi'
47
+ assert_equal LatexEval::Latex.new(latex).equation, '2*xi'
48
+ end
49
+
50
+ def test_that_latex_parser_adds_missing_multiplication_after_variable
51
+ latex = '\xi2'
52
+ assert_equal LatexEval::Latex.new(latex).equation, 'xi*2'
53
+ end
54
+
55
+ def test_that_latex_parser_adds_missing_multiplication_between_variable
56
+ latex = '\alpha\beta'
57
+ assert_equal LatexEval::Latex.new(latex).equation, 'alpha*beta'
58
+ end
59
+
60
+ def test_that_latex_parser_adds_missing_multiplication_between_brackets
61
+ latex = '(1)(2)'
62
+ assert_equal LatexEval::Latex.new(latex).equation, '(1)*(2)'
63
+ end
64
+
65
+ def test_that_latex_parser_parses_nth_root
66
+ latex = '\sqrt[3]{2}'
67
+ assert_equal LatexEval::Latex.new(latex).equation, '((2)^(1/(3)))'
68
+ end
69
+
70
+ def test_that_latex_parser_parses_sqrt
71
+ latex = '\sqrt{2}'
72
+ assert_equal LatexEval::Latex.new(latex).equation, '((2)^(1/2))'
73
+ end
74
+
75
+ def test_works_with_typical_variables
76
+ latex = '\xi x'
77
+ assert_equal LatexEval::Latex.new(latex).equation, 'xi*x'
78
+ end
79
+
80
+ def test_works_with_typical_variable
81
+ latex = '2x'
82
+ assert_equal LatexEval::Latex.new(latex).equation, '2*x'
83
+ end
84
+
85
+ def test_works_with_typical_variable_spaces
86
+ latex = '2 x'
87
+ assert_equal LatexEval::Latex.new(latex).equation, '2*x'
88
+ end
89
+
90
+ def test_works_with_typical_variable_multiple_spaces
91
+ latex = '2 x'
92
+ assert_equal LatexEval::Latex.new(latex).equation, '2*x'
93
+ end
94
+
95
+ def test_works_with_left_and_right
96
+ latex = '\left(x + 2\right)'
97
+ assert_equal LatexEval::Latex.new(latex).equation, '(x+2)'
98
+ end
99
+
100
+ def test_works_with_abs
101
+ latex = '2 % 3'
102
+ assert_equal LatexEval::Latex.new(latex).equation, '2%3'
103
+ end
104
+
105
+ def test_works_with_abs_and_variables
106
+ latex = 'x % y'
107
+ assert_equal LatexEval::Latex.new(latex).equation, 'x%y'
108
+ end
109
+
110
+ def test_works_with_variable_spaces
111
+ latex = 'x y'
112
+ assert_equal LatexEval::Latex.new(latex).equation, 'x*y'
113
+ end
114
+
115
+ def test_works_with_latex_variables
116
+ latex = '\xix'
117
+ assert_equal LatexEval::Latex.new(latex).equation, 'xi*x'
118
+ end
119
+
120
+ def test_works_with_regular_variables
121
+ latex = 'xyz'
122
+ assert_equal LatexEval::Latex.new(latex).equation, 'x*y*z'
123
+ end
124
+
125
+ def test_works_with_regular_variables_and_weird_numbers
126
+ latex = 'x*2yz'
127
+ assert_equal LatexEval::Latex.new(latex).equation, 'x*2*y*z'
128
+ end
129
+
130
+ def test_works_with_regular_variables_complex
131
+ latex = '\frac{2xy}{3}'
132
+ assert_equal LatexEval::Latex.new(latex).equation, '((2*x*y)/(3))'
133
+ end
134
+ end
@@ -0,0 +1,54 @@
1
+ require 'minitest/autorun'
2
+ require_relative './../lib/latex_eval.rb'
3
+
4
+ class TestPostfixNotation < Minitest::Test
5
+ def test_that_eval_evals_add
6
+ parsed = [3, 5, :add]
7
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, 8
8
+ end
9
+
10
+ def test_that_eval_evals_subtract
11
+ parsed = [3, 5, :subtract]
12
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, -2
13
+ end
14
+
15
+ def test_that_eval_evals_multiply
16
+ parsed = [3, 5, :multiply]
17
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, 15
18
+ end
19
+
20
+ def test_that_eval_evals_divide
21
+ parsed = [3, 5, :divide]
22
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, 0.6
23
+ end
24
+
25
+ def test_that_eval_evals_power
26
+ parsed = [3, 5, :power]
27
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, 243
28
+ end
29
+
30
+ def test_that_eval_evals_variables
31
+ parsed = [:x, :y, :power]
32
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval({x: 13, y: 3}), 2197
33
+ end
34
+
35
+ def test_that_negatives_work
36
+ parsed = [-2, -1, :subtract]
37
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, -1
38
+ end
39
+
40
+ def test_that_uniary_negative_works
41
+ parsed = [-2, -1, :negative, :add]
42
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, -1
43
+ end
44
+
45
+ def test_that_uniary_positive_works
46
+ parsed = [-2, -1, :positive, :add]
47
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, -3
48
+ end
49
+
50
+ def test_that_modulus_works
51
+ parsed = [432, 123, :mod]
52
+ assert_equal LatexEval::PostfixNotation.new(parsed).eval, 63
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: latex_eval
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Josh Dunn
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.11'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 5.11.3
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '5.11'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 5.11.3
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '12.3'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '12.3'
47
+ description: This gem can be used to parse and then evaluate simple latex expressions.
48
+ email: jdunn45@alumni.uwo.ca
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - README.md
54
+ - lib/latex_eval.rb
55
+ - lib/latex_eval/equation.rb
56
+ - lib/latex_eval/latex.rb
57
+ - lib/latex_eval/postfix_notation.rb
58
+ - test/equation_test.rb
59
+ - test/latex_eval_test.rb
60
+ - test/latex_test.rb
61
+ - test/postfix_notation_test.rb
62
+ homepage: https://rubygems.org/gems/latex_eval
63
+ licenses:
64
+ - MIT
65
+ metadata:
66
+ source_code_uri: https://github.com/joshddunn/latex_eval
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.6.11
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Evaluate simple latex expressions.
87
+ test_files: []