Last active
August 29, 2015 14:21
-
-
Save fledman/886e463942270c36db08 to your computer and use it in GitHub Desktop.
Chained Arithmetic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DotMath | |
NUMBERS = { | |
zero: 0, one: 1, two: 2, three: 3, four: 4, five: 5, | |
six: 6, seven: 7, eight: 8, nine: 9, ten: 10 | |
}.freeze | |
OPERATORS = { | |
plus: [:+,1], minus: [:-,1], times: [:*,1], divide: [:/,1], | |
negate: [:-@,0], abs: [:abs,0], pow: [:**, 1], mod: [:%, 1] | |
}.freeze | |
OPERATORS.each do |m,op| | |
define_method(m) { apply(op) } | |
end | |
NUMBERS.each do |m, num| | |
define_method(m) { apply(num) } | |
Kernel.send(:define_method, m) { DotMath.new.send(m) } | |
end | |
def initialize(*ops) | |
@queue = ops.compact | |
end | |
def simplify | |
self.class.new(evaluate) | |
end | |
def to_i | |
evaluate | |
end | |
def to_s | |
to_i.to_s | |
end | |
def literal(x) | |
apply(x.to_i) | |
end | |
alias_method :[], :literal | |
private | |
def apply(x) | |
self.class.new(*@queue, x) | |
end | |
def evaluate | |
return if @queue.empty? | |
result = @queue[0].to_i | |
applying, args = nil, [] | |
@queue[1..-1].each do |op| | |
if applying.nil? | |
raise "Expected an operator!" if !op.is_a?(Array) | |
applying = op | |
else | |
raise "Expected an operand!" if op.is_a?(Array) | |
args << op.to_i | |
end | |
if args.size == applying[1] | |
result = result.send(applying[0], *args) | |
applying, args = nil, [] | |
end | |
end | |
raise "Expression is incomplete!" if !applying.nil? || !args.empty? | |
result | |
end | |
end | |
raise "expected (3+4)*5 to equal 35!" if three.plus.four.times.five.to_i != 35 | |
raise "expected 3+(4*5) to equal 23!" if three.plus[four.times.five].to_i != 23 | |
raise "expected (5-1)/2 to equal 2!" if five.minus.one.divide.two.to_i != 2 | |
raise "expected 2 raised to the 4th power to equal 16!" if two.pow.four.to_i != 16 | |
raise "expected (10+2) modulo 5 to equal 2!" if ten.plus.two.mod.five.to_i != 2 | |
raise "expected -3 * 5 to equal -15!" if three.negate.times.five.to_i != -15 | |
raise "expected abs(-(9*1+6) - 8) to equal 23!" if nine.times.one.plus.six.negate.minus.eight.abs.to_i != 23 | |
raise "expected 7 to the 0th power to equal 1!" if seven.pow.zero.to_i != 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment