-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreversePolish.rb
91 lines (70 loc) · 2.28 KB
/
reversePolish.rb
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
=begin
Source: Something I came up with for practice, based on the math_eval challenge.
Description:
First:
Using arrays as stacks, write a function called 'to_postfix' that will parse
an input string in infix notation and convert it to postfix (reverse polish) notation.
Example: to_postfix('1 + 2 - 3 / 4 * 5') => '1 2 + 3 4 / 5 * -'
Second:
Using arrays as stacks, write a function called 'postfix_eval'
that will parse and evaluate a math operation in postfix notation.
Example: postfix_eval('1 2 + 3 4 / 5 * -') => '-0.75'
Bonus:
Using arrays as stacks, use what you learned from the first two challenges to write a
function called 'infix_eval' that will parse and evaluate a math operation in infix notation.
Example: infix_eval('1 + 2 - 3 / 4 * 5') => '-0.75'
=end
# first: parses an infix string ('1 + 2 - 3 / 4 * 5') and converts it to a postfix string ('1 2 + 3 4 / 5 * -')
VALUE = {'-' => 0, '+' => 0, '*' => 1, '/' => 2, nil => -1}
def to_postfix(string)
stack = []
ops = []
string.split(" ").each do |e|
if e.match(/\d+/) then stack << e
else
priority(ops, e).each { |op| stack << op }
ops << e
end
end
stack << ops.pop while !ops.empty?
stack.join(' ')
end
def priority(ops, op2) # helper function for 'to_postfix'
push_ops = []
push_ops << ops.pop while VALUE[ops.last] >= VALUE[op2]
push_ops
end
# second: parses a postfix string ('1 2 + 3 4 / 5 * -') and evaluates it ('-0.75')
def postfix_eval(string)
stack = []
string.split(' ').each do |e|
if e.match(/\d+/) then stack << e.to_f
else
y = stack.pop
x = stack.pop
stack << x.send(e, y)
end
end
stack.last || 0
end
# bonus: parses and infix string ('1 + 2 - 3 / 4 * 5') and evaluates it (-0.75)
VAL = {'-' => 0, '+' => 0, '*' => 1, '/' => 2, nil => -1}
def infix_eval( string )
nums = []
ops = []
string.split(" ").each do |e|
if e.match(/\d+/) then nums << e.to_f
else
eval_triplet( ops.pop, nums ) while VAL[ops.last] >= VAL[e]
ops << e
end
end
eval_triplet( ops.pop, nums ) while !ops.empty?
nums.last || 0
end
# helper function for #infix_eval
def eval_triplet(operation, nums)
y = nums.pop
x = nums.pop
nums << x.send(operation, y)
end