latex_eval 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []