Skip to content

Instantly share code, notes, and snippets.

@lithtle
Created October 23, 2012 11:49
Show Gist options
  • Save lithtle/3938358 to your computer and use it in GitHub Desktop.
Save lithtle/3938358 to your computer and use it in GitHub Desktop.
再挑戦四則演算
# -*- coding:utf-8 -*-
Inf = 1.0 / 0
class Operator
def initialize(a, b)
@left = a
@right = b
end
attr_reader :left, :right
end
class Calculator
def initialize(c)
@fomula = c
@result = calc(c)
end
def calc(c)
case c
when Plus
return calc(c.left) + calc(c.right)
when Minus
return calc(c.left) - calc(c.right)
when Mul
return calc(c.left) * calc(c.right)
when Div
begin
calc(c.left) / calc(c.right)
rescue
return Inf
end
else
return c.to_f
end
end
def to_s
def s(c)
case c
when Plus
return "(" + s(c.left) + "+" + s(c.right) + ")"
when Minus
return "(" + s(c.left) + "-" + s(c.right) + ")"
when Mul
return "(" + s(c.left) + "*" + s(c.right) + ")"
when Div
return "(" + s(c.left) + "/" + s(c.right) + ")"
else
c.to_s
end
end
return s(@fomula)
end
attr_reader :result
end
class Plus < Operator
end
class Minus < Operator
end
class Mul < Operator
end
class Div < Operator
end
def get_numbers(arg)
s = :a
e = s
(arg.length - 1).times{e = e.succ}
a = (s..e).to_a
ret = a.repeated_permutation(arg.length).to_a.map(&:uniq).map{|i| if i.length == arg.length then i end}.compact
ret.each do |unit| # => [:a, :b, ...]
a.each_with_index do |item, j|
unit.map!{|k| if item == k then arg[j] else k end}
end
end
return ret
end
def arith(*arg)
results = []
operators = [Plus, Minus, Mul, Div].repeated_permutation(3).to_a
number_permutation = get_numbers(arg).uniq
number_permutation.each do |i| # i => [a, b, c, d]
a, b, c, d = i
operators.each do |j| # j => 3 of [Plus, Minus, Mul, Div]
s, t, u = j
results << s.new(t.new(a, b), u.new(c, d))
results << s.new(a, t.new(b, u.new(c, d)))
results << s.new(t.new(u.new(a, b), c), d)
results << s.new(t.new(a, u.new(b, c)), d)
results << s.new(a, t.new(u.new(b, c), d))
end
end
results.each_with_index do |item, index|
calculator = Calculator.new(item)
begin
printf "%5d: %s = %.3f\n", index + 1, calculator.to_s, calculator.result
rescue
printf "%5d: %s = %s\n", index + 1, calculator.to_s, "Infinity"
end
end
end
def main
return puts "error: use ruby version > 1.8.* " if RUBY_VERSION <= "1.8.7"
return unless ARGV.length == 4
a, b, c, d = ARGV.map{|i| i.to_i}
arith(a, b, c, d)
# test 1 あとで spec で書き直したいな
c = Calculator.new(Plus.new(2, Plus.new(3, Minus.new(2, 1))))
p c.result # => 6
# test 2
p c.to_s
end
if $0 == __FILE__
main()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment