Решение на Трета задача от Александър Иванов

Обратно към всички решения

Към профила на Александър Иванов

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 13 успешни тест(а)
  • 0 неуспешни тест(а)

Код

class Expr
attr_accessor :arguments
def self.build(data)
return data unless data.is_a? Array
first_expr = Expr.build(data[1])
second_expr = Expr.build(data[2]) unless data[2].nil?
Expr._build(data.first, first_expr, second_expr)
end
def self._build(type, first_expr, second_expr)
case type
when :number then Number.new first_expr
when :variable then Variable.new first_expr
when :+ then Addition.new first_expr, second_expr
when :- then Negation.new first_expr
when :* then Multiplication.new first_expr, second_expr
when :sin then Sine.new first_expr
when :cos then Cosine.new first_expr
end
end
def ==(other)
self.class == other.class and
self.arguments == other.arguments
end
alias :eql? :==
def +(other)
Addition.new self, other
end
def *(other)
Multiplication.new self, other
end
def -@
Negation.new self
end
def exact?
@arguments.all?(&:exact?)
end
def evaluate(variables)
raise Exception.new '#evaluate not implemented'
end
def simplify
raise Exception.new '#simplify not implemented'
end
def derive(variable)
raise Exception.new '#derive not implemented'
end
end
class Unary < Expr
def initialize(expr)
@arguments = [expr]
end
def argument
@arguments.first
end
end
class Binary < Expr
def initialize(first_expr, second_expr)
@arguments = [first_expr, second_expr]
end
end
class Number < Unary
def evaluate(variables)
argument
end
def simplify
Number.new argument
end
def derive(variable)
Number.new 0
end
def exact?
true
end
def to_s
argument
end
end
class Addition < Binary
def evaluate(variables)
@arguments[0].evaluate(variables) + @arguments[1].evaluate(variables)
end
def simplify
return Number.new evaluate(nil) if exact?
first_expr = @arguments[0].simplify
second_expr = @arguments[1].simplify
zero = Number.new 0
return second_expr if first_expr == zero
return first_expr if second_expr == zero
Addition.new first_expr, second_expr
end
def derive(variable)
expr = simplify
return expr.derive(variable) unless expr.is_a? Addition
Addition.new(expr.arguments[0].derive(variable), expr.arguments[1].derive(variable)).simplify
end
def to_s
'(' + @arguments.map(&:to_s).join('+') + ')'
end
end
class Multiplication < Binary
def evaluate(variables)
@arguments[0].evaluate(variables) * @arguments[1].evaluate(variables)
end
def simplify
return Number.new evaluate(nil) if exact?
first_expr = @arguments[0].simplify
second_expr = @arguments[1].simplify
zero = Number.new 0
one = Number.new 1
return zero if first_expr == zero or second_expr == zero
return second_expr if first_expr == one
return first_expr if second_expr == one
Multiplication.new first_expr, second_expr
end
def derive(variable)
expr = simplify
return expr.derive(variable) unless expr.is_a? Multiplication
return expr.arguments[0] if expr.arguments[0].exact?
return expr.arguments[1] if expr.arguments[1].exact?
first_expr = Multiplication.new expr.arguments[0].derive(variable), expr.arguments[1]
second_expr = Multiplication.new expr.arguments[0], expr.arguments[1].derive(variable)
Addition.new(first_expr, second_expr).simplify
end
def to_s
'(' + @arguments.map(&:to_s).join('*') + ')'
end
end
class Variable < Unary
def evaluate(variables)
raise Exception.new "Cannot evaluate variable (#{argument})" unless variables.has_key? argument
variables[argument]
end
def simplify
Variable.new argument
end
def derive(variable)
if variable == argument
Number.new 1
else
Number.new 0
end
end
def exact?
false
end
def to_s
argument
end
end
class Negation < Unary
def evaluate(variables)
-1 * argument.evaluate(variables)
end
def simplify
return Number.new evaluate(nil) if exact?
Negation.new argument.simplify
end
def derive(variable)
Negation.new(argument.derive(variable)).simplify
end
def to_s
"-#{argument}"
end
end
class Sine < Unary
def evaluate(variables)
Math.sin argument.evaluate(variables)
end
def simplify
return Number.new evaluate(nil) if exact?
Sine.new argument.simplify
end
def derive(variable)
expr = simplify
return expr.derive(variable) unless expr.is_a? Sine
derivative = expr.argument.derive(variable)
cosine = Cosine.new expr.argument
Multiplication.new(derivative, cosine).simplify
end
def to_s
"sin(#{argument})"
end
end
class Cosine < Unary
def evaluate(variables)
Math.cos argument.evaluate(variables)
end
def simplify
return Number.new evaluate(nil) if exact?
Cosine.new argument.simplify
end
def derive(variable)
expr = simplify
return expr.derive(variable) unless expr.is_a? Cosine
derivative = expr.argument.derive(variable)
negative_sine = Negation.new Sine.new(expr.argument)
Multiplication.new(derivative, negative_sine).simplify
end
def to_s
"cos(#{argument})"
end
end

Лог от изпълнението

.............

Finished in 0.05057 seconds
13 examples, 0 failures

История (1 версия и 0 коментара)

Александър обнови решението на 14.11.2012 01:28 (преди над 11 години)

+class Expr
+ attr_accessor :arguments
+
+ def self.build(data)
+ return data unless data.is_a? Array
+
+ first_expr = Expr.build(data[1])
+ second_expr = Expr.build(data[2]) unless data[2].nil?
+
+ Expr._build(data.first, first_expr, second_expr)
+ end
+
+ def self._build(type, first_expr, second_expr)
+ case type
+ when :number then Number.new first_expr
+ when :variable then Variable.new first_expr
+ when :+ then Addition.new first_expr, second_expr
+ when :- then Negation.new first_expr
+ when :* then Multiplication.new first_expr, second_expr
+ when :sin then Sine.new first_expr
+ when :cos then Cosine.new first_expr
+ end
+ end
+
+ def ==(other)
+ self.class == other.class and
+ self.arguments == other.arguments
+ end
+
+ alias :eql? :==
+
+ def +(other)
+ Addition.new self, other
+ end
+
+ def *(other)
+ Multiplication.new self, other
+ end
+
+ def -@
+ Negation.new self
+ end
+
+ def exact?
+ @arguments.all?(&:exact?)
+ end
+
+ def evaluate(variables)
+ raise Exception.new '#evaluate not implemented'
+ end
+
+ def simplify
+ raise Exception.new '#simplify not implemented'
+ end
+
+ def derive(variable)
+ raise Exception.new '#derive not implemented'
+ end
+end
+
+class Unary < Expr
+ def initialize(expr)
+ @arguments = [expr]
+ end
+
+ def argument
+ @arguments.first
+ end
+end
+
+class Binary < Expr
+ def initialize(first_expr, second_expr)
+ @arguments = [first_expr, second_expr]
+ end
+end
+
+class Number < Unary
+ def evaluate(variables)
+ argument
+ end
+
+ def simplify
+ Number.new argument
+ end
+
+ def derive(variable)
+ Number.new 0
+ end
+
+ def exact?
+ true
+ end
+
+ def to_s
+ argument
+ end
+end
+
+class Addition < Binary
+ def evaluate(variables)
+ @arguments[0].evaluate(variables) + @arguments[1].evaluate(variables)
+ end
+
+ def simplify
+ return Number.new evaluate(nil) if exact?
+
+ first_expr = @arguments[0].simplify
+ second_expr = @arguments[1].simplify
+ zero = Number.new 0
+
+ return second_expr if first_expr == zero
+ return first_expr if second_expr == zero
+
+ Addition.new first_expr, second_expr
+ end
+
+ def derive(variable)
+ expr = simplify
+
+ return expr.derive(variable) unless expr.is_a? Addition
+
+ Addition.new(expr.arguments[0].derive(variable), expr.arguments[1].derive(variable)).simplify
+ end
+
+ def to_s
+ '(' + @arguments.map(&:to_s).join('+') + ')'
+ end
+end
+
+class Multiplication < Binary
+ def evaluate(variables)
+ @arguments[0].evaluate(variables) * @arguments[1].evaluate(variables)
+ end
+
+ def simplify
+ return Number.new evaluate(nil) if exact?
+
+ first_expr = @arguments[0].simplify
+ second_expr = @arguments[1].simplify
+ zero = Number.new 0
+ one = Number.new 1
+
+ return zero if first_expr == zero or second_expr == zero
+ return second_expr if first_expr == one
+ return first_expr if second_expr == one
+
+ Multiplication.new first_expr, second_expr
+ end
+
+ def derive(variable)
+ expr = simplify
+
+ return expr.derive(variable) unless expr.is_a? Multiplication
+
+ return expr.arguments[0] if expr.arguments[0].exact?
+ return expr.arguments[1] if expr.arguments[1].exact?
+
+ first_expr = Multiplication.new expr.arguments[0].derive(variable), expr.arguments[1]
+ second_expr = Multiplication.new expr.arguments[0], expr.arguments[1].derive(variable)
+
+ Addition.new(first_expr, second_expr).simplify
+ end
+
+ def to_s
+ '(' + @arguments.map(&:to_s).join('*') + ')'
+ end
+end
+
+class Variable < Unary
+ def evaluate(variables)
+ raise Exception.new "Cannot evaluate variable (#{argument})" unless variables.has_key? argument
+ variables[argument]
+ end
+
+ def simplify
+ Variable.new argument
+ end
+
+ def derive(variable)
+ if variable == argument
+ Number.new 1
+ else
+ Number.new 0
+ end
+ end
+
+ def exact?
+ false
+ end
+
+ def to_s
+ argument
+ end
+end
+
+class Negation < Unary
+ def evaluate(variables)
+ -1 * argument.evaluate(variables)
+ end
+
+ def simplify
+ return Number.new evaluate(nil) if exact?
+ Negation.new argument.simplify
+ end
+
+ def derive(variable)
+ Negation.new(argument.derive(variable)).simplify
+ end
+
+ def to_s
+ "-#{argument}"
+ end
+end
+
+class Sine < Unary
+ def evaluate(variables)
+ Math.sin argument.evaluate(variables)
+ end
+
+ def simplify
+ return Number.new evaluate(nil) if exact?
+ Sine.new argument.simplify
+ end
+
+ def derive(variable)
+ expr = simplify
+
+ return expr.derive(variable) unless expr.is_a? Sine
+
+ derivative = expr.argument.derive(variable)
+ cosine = Cosine.new expr.argument
+
+ Multiplication.new(derivative, cosine).simplify
+ end
+
+ def to_s
+ "sin(#{argument})"
+ end
+end
+
+class Cosine < Unary
+ def evaluate(variables)
+ Math.cos argument.evaluate(variables)
+ end
+
+ def simplify
+ return Number.new evaluate(nil) if exact?
+ Cosine.new argument.simplify
+ end
+
+ def derive(variable)
+ expr = simplify
+
+ return expr.derive(variable) unless expr.is_a? Cosine
+
+ derivative = expr.argument.derive(variable)
+ negative_sine = Negation.new Sine.new(expr.argument)
+
+ Multiplication.new(derivative, negative_sine).simplify
+ end
+
+ def to_s
+ "cos(#{argument})"
+ end
+end