Решение на Трета задача от Милан Миланов

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

Към профила на Милан Миланов

Резултати

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

Код

class Expr
attr_reader :expression
def initialize(expression)
@expression = expression
end
def evaluate(variables = {})
@expression.evaluate variables
end
def self.build(expression)
Expr.new(Expr.build_expression(expression))
end
def simplify
Expr.new @expression.simplify
end
def derive(argument)
@expression.derive(argument)
Expr.new @expression.derive(argument).simplify
end
def ==(other)
@expression == other.expression
end
def self.build_expression(expression)
type, first_value, second_value = expression
case type
when :number then Number.new first_value
when :variable then Variable.new first_value
when :- then Negation.new build_expression(first_value)
when :sin then Sine.new build_expression(first_value)
when :cos then Cosine.new build_expression(first_value)
when :+ then Addition.new(build_expression(first_value), build_expression(second_value))
when :* then Multiplication.new(build_expression(first_value), build_expression(second_value))
end
end
end
class Number < Expr
attr_reader :value
def initialize(value)
@value = value
end
def simplify
Number.new @value
end
def exact?
true
end
def evaluate(environment = {})
@value
end
def derive(argument)
Number.new 0
end
def ==(other)
@value == other.value
end
end
class Addition < Expr
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def simplify
if @left.exact? and @right.exact?
Number.new(@left.evaluate + @right.evaluate)
elsif @left.exact?
simplify_result(@left, @right)
elsif @right.exact?
simplify_result(@right, @left)
else
Addition.new(@left.simplify, @right.simplify)
end
end
def exact?
@left.exact? && @right.exact?
end
def evaluate(environment = {})
@left.evaluate(environment) + @right.evaluate(environment)
end
def derive(argument)
Addition.new(@left.derive(argument), @right.derive(argument))
end
def ==(other)
self.class == other.class ? (@left == other.left and @right == other.right) : false
end
private
def simplify_result(operand_main, operand_secondary)
evaluation = operand_main.evaluate
evaluation.zero? ? operand_secondary.simplify : Number.new(operand_main.evaluate)
end
end
class Multiplication < Expr
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def simplify
if @left.exact? and @right.exact?
Number.new(@left.evaluate * @right.evaluate)
elsif @left.exact?
simplify_result(@left, @right)
elsif @right.exact?
simplify_result(@right, @left)
else
Multiplication.new(@left.simplify, @right.simplify)
end
end
def exact?
@left.exact? && @right.exact?
end
def evaluate(environment = {})
@left.evaluate(environment) * @right.evaluate(environment)
end
def derive(argument)
left_argument = Multiplication.new(@left.derive(argument), @right)
right_argument = Multiplication.new(@left, @right.derive(argument))
Addition.new(left_argument, right_argument)
end
def ==(other)
self.class == other.class ? (@left == other.left and @right == other.right) : false
end
private
def simplify_result(operand_main, operand_secondary)
evaluation = operand_main.evaluate
if evaluation == 0
Number.new 0
elsif evaluation == 1
operand_secondary.simplify
else
Multiplication.new(Number.new(evaluation), operand_secondary.simplify).simplify
end
end
end
class Variable < Expr
attr_reader :value
def initialize(value)
@value = value
end
def simplify
Variable.new @value
end
def exact?
false
end
def evaluate(environment = {})
raise "Use of unassigned local variable #@value" unless environment.has_key?(@value)
environment[@value]
end
def derive(argument)
@value == argument ? Number.new(1) : Number.new(0)
end
def ==(other)
self.class == other.class ? @value == other.value : false
end
end
class Negation < Expr
attr_reader :value
def initialize(value)
@value = value
end
def simplify
@value.exact? ? Number.new(evaluate) : Negation.new(@value.simplify)
end
def exact?
@value.exact?
end
def evaluate(environment = {})
-@value.evaluate(environment)
end
def derive(argument)
Negation.new(@value.derive(argument))
end
def ==(other)
self.class == other.class ? @value == other.value : false
end
end
class Sine < Expr
attr_reader :value
def initialize(value)
@value = value
end
def simplify
@value.exact? ? Number.new(evaluate) : Sine.new(@value.simplify)
end
def exact?
@value.exact?
end
def evaluate(environment = {})
Math.sin(@value.evaluate(environment))
end
def derive(argument)
left_argument = @value.derive argument
right_argument = Cosine.new @value
Multiplication.new(left_argument, right_argument)
end
def ==(other)
self.class == other.class ? @value == other.value : false
end
end
class Cosine < Expr
attr_reader :value
def initialize(value)
@value = value
end
def simplify
@value.exact? ? Number.new(evaluate) : Cosine.new(@value.simplify)
end
def exact?
@value.exact?
end
def evaluate(environment = {})
Math.cos(@value.evaluate(environment))
end
def derive(argument)
left_argument = @value.derive argument
right_argument = Negation.new(Sine.new(@value))
Multiplication.new(left_argument, right_argument)
end
def ==(other)
self.class == other.class ? @value == other.value : false
end
end

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

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

Finished in 0.04952 seconds
13 examples, 0 failures

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

Милан обнови решението на 12.11.2012 18:04 (преди над 11 години)

+class Expr
+ attr_reader :expression
+
+ def initialize(expression)
+ @expression = expression
+ end
+
+ def evaluate(variables = {})
+ @expression.evaluate variables
+ end
+
+ def self.build(expression)
+ Expr.new(Expr.build_expression(expression))
+ end
+
+ def simplify
+ Expr.new @expression.simplify
+ end
+
+ def derive(argument)
+ @expression.derive(argument)
+ Expr.new @expression.derive(argument).simplify
+ end
+
+ def ==(other)
+ @expression == other.expression
+ end
+
+ def self.build_expression(expression)
+ type, first_value, second_value = expression
+ case type
+ when :number then Number.new first_value
+ when :variable then Variable.new first_value
+ when :- then Negation.new build_expression(first_value)
+ when :sin then Sine.new build_expression(first_value)
+ when :cos then Cosine.new build_expression(first_value)
+ when :+ then Addition.new(build_expression(first_value), build_expression(second_value))
+ when :* then Multiplication.new(build_expression(first_value), build_expression(second_value))
+ end
+ end
+end
+
+class Number < Expr
+ attr_reader :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def simplify
+ Number.new @value
+ end
+
+ def exact?
+ true
+ end
+
+ def evaluate(environment = {})
+ @value
+ end
+
+ def derive(argument)
+ Number.new 0
+ end
+
+ def ==(other)
+ @value == other.value
+ end
+end
+
+class Addition < Expr
+ attr_reader :left, :right
+
+ def initialize(left, right)
+ @left = left
+ @right = right
+ end
+
+ def simplify
+ if @left.exact? and @right.exact?
+ Number.new(@left.evaluate + @right.evaluate)
+ elsif @left.exact?
+ simplify_result(@left, @right)
+ elsif @right.exact?
+ simplify_result(@right, @left)
+ else
+ Addition.new(@left.simplify, @right.simplify)
+ end
+ end
+
+ def exact?
+ @left.exact? && @right.exact?
+ end
+
+ def evaluate(environment = {})
+ @left.evaluate(environment) + @right.evaluate(environment)
+ end
+
+ def derive(argument)
+ Addition.new(@left.derive(argument), @right.derive(argument))
+ end
+
+ def ==(other)
+ self.class == other.class ? (@left == other.left and @right == other.right) : false
+ end
+
+ private
+ def simplify_result(operand_main, operand_secondary)
+ evaluation = operand_main.evaluate
+ evaluation.zero? ? operand_secondary.simplify : Number.new(operand_main.evaluate)
+ end
+end
+
+class Multiplication < Expr
+ attr_reader :left, :right
+
+ def initialize(left, right)
+ @left = left
+ @right = right
+ end
+
+ def simplify
+ if @left.exact? and @right.exact?
+ Number.new(@left.evaluate * @right.evaluate)
+ elsif @left.exact?
+ simplify_result(@left, @right)
+ elsif @right.exact?
+ simplify_result(@right, @left)
+ else
+ Multiplication.new(@left.simplify, @right.simplify)
+ end
+ end
+
+ def exact?
+ @left.exact? && @right.exact?
+ end
+
+ def evaluate(environment = {})
+ @left.evaluate(environment) * @right.evaluate(environment)
+ end
+
+ def derive(argument)
+ left_argument = Multiplication.new(@left.derive(argument), @right)
+ right_argument = Multiplication.new(@left, @right.derive(argument))
+ Addition.new(left_argument, right_argument)
+ end
+
+ def ==(other)
+ self.class == other.class ? (@left == other.left and @right == other.right) : false
+ end
+
+ private
+ def simplify_result(operand_main, operand_secondary)
+ evaluation = operand_main.evaluate
+ if evaluation == 0
+ Number.new 0
+ elsif evaluation == 1
+ operand_secondary.simplify
+ else
+ Multiplication.new(Number.new(evaluation), operand_secondary.simplify).simplify
+ end
+ end
+end
+
+class Variable < Expr
+ attr_reader :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def simplify
+ Variable.new @value
+ end
+
+ def exact?
+ false
+ end
+
+ def evaluate(environment = {})
+ raise "Use of unassigned local variable #@value" unless environment.has_key?(@value)
+ environment[@value]
+ end
+
+ def derive(argument)
+ @value == argument ? Number.new(1) : Number.new(0)
+ end
+
+ def ==(other)
+ self.class == other.class ? @value == other.value : false
+ end
+end
+
+class Negation < Expr
+ attr_reader :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def simplify
+ @value.exact? ? Number.new(evaluate) : Negation.new(@value.simplify)
+ end
+
+ def exact?
+ @value.exact?
+ end
+
+ def evaluate(environment = {})
+ -@value.evaluate(environment)
+ end
+
+ def derive(argument)
+ Negation.new(@value.derive(argument))
+ end
+
+ def ==(other)
+ self.class == other.class ? @value == other.value : false
+ end
+end
+
+class Sine < Expr
+ attr_reader :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def simplify
+ @value.exact? ? Number.new(evaluate) : Sine.new(@value.simplify)
+ end
+
+ def exact?
+ @value.exact?
+ end
+
+ def evaluate(environment = {})
+ Math.sin(@value.evaluate(environment))
+ end
+
+ def derive(argument)
+ left_argument = @value.derive argument
+ right_argument = Cosine.new @value
+ Multiplication.new(left_argument, right_argument)
+ end
+
+ def ==(other)
+ self.class == other.class ? @value == other.value : false
+ end
+end
+
+class Cosine < Expr
+ attr_reader :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def simplify
+ @value.exact? ? Number.new(evaluate) : Cosine.new(@value.simplify)
+ end
+
+ def exact?
+ @value.exact?
+ end
+
+ def evaluate(environment = {})
+ Math.cos(@value.evaluate(environment))
+ end
+
+ def derive(argument)
+ left_argument = @value.derive argument
+ right_argument = Negation.new(Sine.new(@value))
+ Multiplication.new(left_argument, right_argument)
+ end
+
+ def ==(other)
+ self.class == other.class ? @value == other.value : false
+ end
+end