Created
October 23, 2012 11:49
-
-
Save lithtle/3938358 to your computer and use it in GitHub Desktop.
再挑戦四則演算
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
# -*- 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