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

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

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

Резултати

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

Код

class Expr
def self.build(expr_tree)
operation = expr_tree[0]
if expr_tree.length == 2
if operation == :number or operation == :variable
Unary.build operation, expr_tree[1]
else
Unary.build operation, build(expr_tree[1])
end
else
Binary.build operation, build(expr_tree[1]), build(expr_tree[2])
end
end
end
class Unary < Expr
def self.build(operation, argument)
case operation
when :sin then Sine.new argument
when :cos then Cosine.new argument
when :- then Negation.new argument
when :number then Number.new argument
when :variable then Variable.new argument
end
end
attr_reader :argument
def initialize(argument)
@argument = argument
end
def ==(other)
self.class == other.class and argument == other.argument
end
end
class Binary < Expr
def self.build(operation, left, right)
case operation
when :+ then Addition.new left, right
when :* then Multiplication.new left, right
end
end
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def ==(other)
self.class == other.class and
left == other.left and
right == other.right
end
end
class Addition < Binary
def evaluate(environment = {})
left.evaluate(environment) + right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate + new_right.evaluate)
elsif new_left.exact? and new_left.evaluate == 0
new_right
elsif new_right.exact? and new_right.evaluate == 0
new_left
else
Addition.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
(Addition.new new_left, new_right).simplify
end
def to_s
"(#{left} + #{right})"
end
end
class Multiplication < Binary
def evaluate(environment = {})
left.evaluate(environment) * right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate * new_right.evaluate)
elsif new_left.exact? and (new_left.evaluate == 1 or new_left.evaluate == 0)
new_left.evaluate == 1 ? new_right : Number.new(0)
elsif new_right.exact? and (new_right.evaluate == 1 or new_right.evaluate == 0)
new_right.evaluate == 1 ? new_left : Number.new(0)
else
Multiplication.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
left_factor = Multiplication.new new_left, right
right_factor = Multiplication.new left, new_right
(Addition.new left_factor, right_factor).simplify
end
def to_s
"(#{left} * #{right})"
end
end
class Number < Unary
def evaluate(environment = {})
argument
end
def exact?
true
end
def simplify
dup
end
def derive(variable)
Number.new 0
end
def to_s
"#{argument}"
end
end
class Variable < Unary
def evaluate(environment = {})
raise ArgumentError unless environment[argument]
environment[argument]
end
def exact?
false
end
def simplify
dup
end
def derive(variable)
argument == variable ? Number.new(1) : Number.new(0)
end
def to_s
"#{argument}"
end
end
class Negation < Unary
def evaluate(environment = {})
-(argument.evaluate environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (-new_argument.evaluate)
else
Negation.new new_argument
end
end
def derive(variable)
(Negation.new argument.derive(variable)).simplify
end
def to_s
"-#{argument}"
end
end
class Sine < Unary
def evaluate(environment = {})
Math.sin argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (Math.sin new_argument.evaluate)
else
Sine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Cosine.new(argument)).simplify
end
def to_s
"sin(#{argument})"
end
end
class Cosine < Unary
def evaluate(environment = {})
Math.cos argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (Math.cos new_argument.evaluate)
else
Cosine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Negation.new(Sine.new(argument))).simplify
end
def to_s
"cos(#{argument})"
end
end

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

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

Finished in 0.06892 seconds
13 examples, 0 failures

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

Кирчо обнови решението на 11.11.2012 18:03 (преди около 12 години)

+class Expr
+ def self.build(expr_tree)
+ operation = expr_tree[0]
+ if expr_tree.length == 2
+ if operation == :number or operation == :variable
+ Unary.build operation, expr_tree[1]
+ else
+ Unary.build operation, build(expr_tree[1])
+ end
+ else
+ Binary.build operation, build(expr_tree[1]), build(expr_tree[2])
+ end
+ end
+end
+
+class Unary < Expr
+ def self.build(operation, argument)
+ case operation
+ when :sin then Sine.new argument
+ when :cos then Cosine.new argument
+ when :- then Negation.new argument
+ when :number then Number.new argument
+ when :variable then Variable.new argument
+ end
+ end
+end
+
+class Binary < Expr
+ def self.build(operation, left, right)
+ case operation
+ when :+ then Addition.new left, right
+ when :* then Multiplication.new left, right
+ end
+ end
+end
+
+class Addition < Binary
+ attr_reader :left, :right
+
+ def initialize(left, right)
+ @left = left
+ @right = right
+ end
+
+ def ==(other)
+ other.class == Addition and
+ left == other.left and
+ right == other.right
+ end
+
+ def evaluate(environment = {})
+ left.evaluate(environment) + right.evaluate(environment)
+ end
+
+ def exact?
+ left.exact? and right.exact?
+ end
+
+ def simplify
+ new_left, new_right = left.simplify, right.simplify
+
+ if new_left.exact? and new_right.exact?
+ Number.new (new_left.evaluate + new_right.evaluate)
+ elsif new_left.exact? and new_left.evaluate == 0
+ new_right
+ elsif new_right.exact? and new_right.evaluate == 0
+ new_left
+ else
+ Addition.new new_left, new_right
+ end
+ end
+
+ def derive(variable)
+ new_left = left.derive variable
+ new_right = right.derive variable
+
+ (Addition.new new_left, new_right).simplify
+ end
+end
+
+class Multiplication < Binary
+ attr_reader :left, :right
+
+ def initialize(left, right)
+ @left = left
+ @right = right
+ end
+
+ def ==(other)
+ other.class == Multiplication and
+ left == other.left and
+ right == other.right
+ end
+
+ def evaluate(environment = {})
+ left.evaluate(environment) * right.evaluate(environment)
+ end
+
+ def exact?
+ left.exact? and right.exact?
+ end
+
+ def simplify
+ new_left, new_right = left.simplify, right.simplify
+
+ if new_left.exact? and new_right.exact?
+ Number.new (new_left.evaluate * new_right.evaluate)
+ elsif new_left.exact? and (new_left.evaluate == 1 or new_left.evaluate == 0)
+ new_left.evaluate == 1 ? new_right : Number.new(0)
+ elsif new_right.exact? and (new_right.evaluate == 1 or new_right.evaluate == 0)
+ new_right.evaluate == 1 ? new_left : Number.new(0)
+ else
+ Multiplication.new new_left, new_right
+ end
+ end
+
+ def derive(variable)
+ new_left = left.derive variable
+ new_right = right.derive variable
+ left_mult = Multiplication.new new_left, right
+ right_mult = Multiplication.new left, new_right
+
+ (Addition.new left_mult, right_mult).simplify
+ end
+end
+
+class Number < Unary
+ attr_reader :argument
+
+ def initialize(argument)
+ @argument = argument
+ end
+
+ def ==(other)
+ other.class == Number and argument == other.argument
+ end
+
+ def evaluate(environment = {})
+ argument
+ end
+
+ def exact?
+ true
+ end
+
+ def simplify
+ dup
+ end
+
+ def derive(variable)
+ Number.new 0
+ end
+end
+
+class Variable < Unary
+ attr_reader :argument
+
+ def initialize(argument)
+ @argument = argument
+ end
+
+ def ==(other)
+ other.class == Variable and argument == other.argument
+ end
+
+ def evaluate(environment = {})
+ raise ArgumentError unless environment[argument]
+
+ environment[argument]
+ end
+
+ def exact?
+ false
+ end
+
+ def simplify
+ dup
+ end
+
+ def derive(variable)
+ argument == variable ? Number.new(1) : Number.new(0)
+ end
+end
+
+class Negation < Unary
+ attr_reader :argument
+
+ def initialize(argument)
+ @argument = argument
+ end
+
+ def ==(other)
+ other.class == Negation and argument == other.argument
+ end
+
+ def evaluate(environment = {})
+ -(argument.evaluate environment)
+ end
+
+ def exact?
+ argument.exact?
+ end
+
+ def simplify
+ new_argument = argument.simplify
+ if new_argument.exact?
+ Number.new (-new_argument.evaluate)
+ else
+ Negation.new new_argument
+ end
+ end
+
+ def derive(variable)
+ (Negation.new argument.derive(variable)).simplify
+ end
+end
+
+class Sine < Unary
+ attr_reader :argument
+
+ def initialize(argument)
+ @argument = argument
+ end
+
+ def ==(other)
+ other.class == Sine and argument == other.argument
+ end
+
+ def evaluate(environment = {})
+ Math.sin argument.evaluate(environment)
+ end
+
+ def exact?
+ argument.exact?
+ end
+
+ def simplify
+ new_argument = argument.simplify
+ if new_argument.exact?
+ Number.new (new_argument.evaluate)
+ else
+ Sine.new new_argument
+ end
+ end
+
+ def derive(variable)
+ argument_derivative = argument.derive variable
+
+ (Multiplication.new argument_derivative, Cosine.new(argument)).simplify
+ end
+end
+
+class Cosine < Unary
+ attr_reader :argument
+
+ def initialize(argument)
+ @argument = argument
+ end
+
+ def ==(other)
+ other.class == Cosine and argument == other.argument
+ end
+
+ def evaluate(environment = {})
+ Math.cos argument.evaluate(environment)
+ end
+
+ def exact?
+ argument.exact?
+ end
+
+ def simplify
+ new_argument = argument.simplify
+ if new_argument.exact?
+ Number.new (new_argument.evaluate)
+ else
+ Cosine.new new_argument
+ end
+ end
+
+ def derive(variable)
+ argument_derivative = argument.derive variable
+
+ (Multiplication.new argument_derivative, Negation.new(Sine.new(argument))).simplify
+ end
+end

Кирчо обнови решението на 11.11.2012 18:13 (преди около 12 години)

class Expr
def self.build(expr_tree)
operation = expr_tree[0]
if expr_tree.length == 2
if operation == :number or operation == :variable
Unary.build operation, expr_tree[1]
else
Unary.build operation, build(expr_tree[1])
end
else
Binary.build operation, build(expr_tree[1]), build(expr_tree[2])
end
end
end
class Unary < Expr
def self.build(operation, argument)
case operation
when :sin then Sine.new argument
when :cos then Cosine.new argument
when :- then Negation.new argument
when :number then Number.new argument
when :variable then Variable.new argument
end
end
end
class Binary < Expr
def self.build(operation, left, right)
case operation
when :+ then Addition.new left, right
when :* then Multiplication.new left, right
end
end
end
class Addition < Binary
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def ==(other)
other.class == Addition and
left == other.left and
right == other.right
end
def evaluate(environment = {})
left.evaluate(environment) + right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate + new_right.evaluate)
elsif new_left.exact? and new_left.evaluate == 0
new_right
elsif new_right.exact? and new_right.evaluate == 0
new_left
else
Addition.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
(Addition.new new_left, new_right).simplify
end
end
class Multiplication < Binary
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def ==(other)
other.class == Multiplication and
left == other.left and
right == other.right
end
def evaluate(environment = {})
left.evaluate(environment) * right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate * new_right.evaluate)
elsif new_left.exact? and (new_left.evaluate == 1 or new_left.evaluate == 0)
new_left.evaluate == 1 ? new_right : Number.new(0)
elsif new_right.exact? and (new_right.evaluate == 1 or new_right.evaluate == 0)
new_right.evaluate == 1 ? new_left : Number.new(0)
else
Multiplication.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
left_mult = Multiplication.new new_left, right
right_mult = Multiplication.new left, new_right
(Addition.new left_mult, right_mult).simplify
end
end
class Number < Unary
attr_reader :argument
def initialize(argument)
@argument = argument
end
def ==(other)
other.class == Number and argument == other.argument
end
def evaluate(environment = {})
argument
end
def exact?
true
end
def simplify
dup
end
def derive(variable)
Number.new 0
end
end
class Variable < Unary
attr_reader :argument
def initialize(argument)
@argument = argument
end
def ==(other)
other.class == Variable and argument == other.argument
end
def evaluate(environment = {})
raise ArgumentError unless environment[argument]
environment[argument]
end
def exact?
false
end
def simplify
dup
end
def derive(variable)
argument == variable ? Number.new(1) : Number.new(0)
end
end
class Negation < Unary
attr_reader :argument
def initialize(argument)
@argument = argument
end
def ==(other)
other.class == Negation and argument == other.argument
end
def evaluate(environment = {})
-(argument.evaluate environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (-new_argument.evaluate)
else
Negation.new new_argument
end
end
def derive(variable)
(Negation.new argument.derive(variable)).simplify
end
end
class Sine < Unary
attr_reader :argument
def initialize(argument)
@argument = argument
end
def ==(other)
other.class == Sine and argument == other.argument
end
def evaluate(environment = {})
Math.sin argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
- Number.new (new_argument.evaluate)
+ Number.new (Math.sin new_argument.evaluate)
else
Sine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Cosine.new(argument)).simplify
end
end
class Cosine < Unary
attr_reader :argument
def initialize(argument)
@argument = argument
end
def ==(other)
other.class == Cosine and argument == other.argument
end
def evaluate(environment = {})
Math.cos argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
- Number.new (new_argument.evaluate)
+ Number.new (Math.cos new_argument.evaluate)
else
Cosine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Negation.new(Sine.new(argument))).simplify
end
end

Кирчо обнови решението на 12.11.2012 13:52 (преди около 12 години)

class Expr
def self.build(expr_tree)
operation = expr_tree[0]
if expr_tree.length == 2
if operation == :number or operation == :variable
Unary.build operation, expr_tree[1]
else
Unary.build operation, build(expr_tree[1])
end
else
Binary.build operation, build(expr_tree[1]), build(expr_tree[2])
end
end
end
class Unary < Expr
def self.build(operation, argument)
case operation
when :sin then Sine.new argument
when :cos then Cosine.new argument
when :- then Negation.new argument
when :number then Number.new argument
when :variable then Variable.new argument
end
end
+
+ attr_reader :argument
+
+ def initialize(argument)
+ @argument = argument
+ end
+
+ def ==(other)
+ self.class == other.class and argument == other.argument
+ end
end
class Binary < Expr
def self.build(operation, left, right)
case operation
when :+ then Addition.new left, right
when :* then Multiplication.new left, right
end
end
-end
-class Addition < Binary
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def ==(other)
- other.class == Addition and
+ self.class == other.class and
left == other.left and
right == other.right
end
+end
+class Addition < Binary
+ def initialize(left, right)
+ super
+ end
+
def evaluate(environment = {})
left.evaluate(environment) + right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate + new_right.evaluate)
elsif new_left.exact? and new_left.evaluate == 0
new_right
elsif new_right.exact? and new_right.evaluate == 0
new_left
else
Addition.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
(Addition.new new_left, new_right).simplify
end
end
class Multiplication < Binary
- attr_reader :left, :right
-
def initialize(left, right)
- @left = left
- @right = right
+ super
end
- def ==(other)
- other.class == Multiplication and
- left == other.left and
- right == other.right
- end
-
def evaluate(environment = {})
left.evaluate(environment) * right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate * new_right.evaluate)
elsif new_left.exact? and (new_left.evaluate == 1 or new_left.evaluate == 0)
new_left.evaluate == 1 ? new_right : Number.new(0)
elsif new_right.exact? and (new_right.evaluate == 1 or new_right.evaluate == 0)
new_right.evaluate == 1 ? new_left : Number.new(0)
else
Multiplication.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
left_mult = Multiplication.new new_left, right
right_mult = Multiplication.new left, new_right
(Addition.new left_mult, right_mult).simplify
end
end
class Number < Unary
- attr_reader :argument
-
def initialize(argument)
- @argument = argument
+ super
end
- def ==(other)
- other.class == Number and argument == other.argument
- end
-
def evaluate(environment = {})
argument
end
def exact?
true
end
def simplify
dup
end
def derive(variable)
Number.new 0
end
end
class Variable < Unary
- attr_reader :argument
-
def initialize(argument)
- @argument = argument
+ super
end
- def ==(other)
- other.class == Variable and argument == other.argument
- end
-
def evaluate(environment = {})
raise ArgumentError unless environment[argument]
environment[argument]
end
def exact?
false
end
def simplify
dup
end
def derive(variable)
argument == variable ? Number.new(1) : Number.new(0)
end
end
class Negation < Unary
- attr_reader :argument
-
def initialize(argument)
- @argument = argument
+ super
end
- def ==(other)
- other.class == Negation and argument == other.argument
- end
-
def evaluate(environment = {})
-(argument.evaluate environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (-new_argument.evaluate)
else
Negation.new new_argument
end
end
def derive(variable)
(Negation.new argument.derive(variable)).simplify
end
end
class Sine < Unary
- attr_reader :argument
-
def initialize(argument)
- @argument = argument
+ super
end
- def ==(other)
- other.class == Sine and argument == other.argument
- end
-
def evaluate(environment = {})
Math.sin argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (Math.sin new_argument.evaluate)
else
Sine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Cosine.new(argument)).simplify
end
end
class Cosine < Unary
- attr_reader :argument
-
def initialize(argument)
- @argument = argument
- end
-
- def ==(other)
- other.class == Cosine and argument == other.argument
+ super
end
def evaluate(environment = {})
Math.cos argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (Math.cos new_argument.evaluate)
else
Cosine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Negation.new(Sine.new(argument))).simplify
end
end

Кирчо обнови решението на 12.11.2012 14:11 (преди около 12 години)

class Expr
def self.build(expr_tree)
operation = expr_tree[0]
if expr_tree.length == 2
if operation == :number or operation == :variable
Unary.build operation, expr_tree[1]
else
Unary.build operation, build(expr_tree[1])
end
else
Binary.build operation, build(expr_tree[1]), build(expr_tree[2])
end
end
end
class Unary < Expr
def self.build(operation, argument)
case operation
when :sin then Sine.new argument
when :cos then Cosine.new argument
when :- then Negation.new argument
when :number then Number.new argument
when :variable then Variable.new argument
end
end
attr_reader :argument
def initialize(argument)
@argument = argument
end
def ==(other)
self.class == other.class and argument == other.argument
end
end
class Binary < Expr
def self.build(operation, left, right)
case operation
when :+ then Addition.new left, right
when :* then Multiplication.new left, right
end
end
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def ==(other)
self.class == other.class and
left == other.left and
right == other.right
end
end
class Addition < Binary
def initialize(left, right)
super
end
def evaluate(environment = {})
left.evaluate(environment) + right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate + new_right.evaluate)
elsif new_left.exact? and new_left.evaluate == 0
new_right
elsif new_right.exact? and new_right.evaluate == 0
new_left
else
Addition.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
(Addition.new new_left, new_right).simplify
end
+
+ def to_s
+ "(#{left} + #{right})"
+ end
end
class Multiplication < Binary
def initialize(left, right)
super
end
def evaluate(environment = {})
left.evaluate(environment) * right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate * new_right.evaluate)
elsif new_left.exact? and (new_left.evaluate == 1 or new_left.evaluate == 0)
new_left.evaluate == 1 ? new_right : Number.new(0)
elsif new_right.exact? and (new_right.evaluate == 1 or new_right.evaluate == 0)
new_right.evaluate == 1 ? new_left : Number.new(0)
else
Multiplication.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
left_mult = Multiplication.new new_left, right
right_mult = Multiplication.new left, new_right
(Addition.new left_mult, right_mult).simplify
end
+
+ def to_s
+ "(#{left} * #{right})"
+ end
end
class Number < Unary
def initialize(argument)
super
end
def evaluate(environment = {})
argument
end
def exact?
true
end
def simplify
dup
end
def derive(variable)
Number.new 0
end
+
+ def to_s
+ "#{argument}"
+ end
end
class Variable < Unary
def initialize(argument)
super
end
def evaluate(environment = {})
raise ArgumentError unless environment[argument]
environment[argument]
end
def exact?
false
end
def simplify
dup
end
def derive(variable)
argument == variable ? Number.new(1) : Number.new(0)
end
+
+ def to_s
+ "#{argument}"
+ end
end
class Negation < Unary
def initialize(argument)
super
end
def evaluate(environment = {})
-(argument.evaluate environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (-new_argument.evaluate)
else
Negation.new new_argument
end
end
def derive(variable)
(Negation.new argument.derive(variable)).simplify
end
+
+ def to_s
+ "-#{argument}"
+ end
end
class Sine < Unary
def initialize(argument)
super
end
def evaluate(environment = {})
Math.sin argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (Math.sin new_argument.evaluate)
else
Sine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Cosine.new(argument)).simplify
end
+
+ def to_s
+ "sin(#{argument})"
+ end
end
class Cosine < Unary
def initialize(argument)
super
end
def evaluate(environment = {})
Math.cos argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (Math.cos new_argument.evaluate)
else
Cosine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Negation.new(Sine.new(argument))).simplify
+ end
+
+ def to_s
+ "cos(#{argument})"
end
end

Кирчо обнови решението на 13.11.2012 14:02 (преди около 12 години)

class Expr
def self.build(expr_tree)
operation = expr_tree[0]
if expr_tree.length == 2
if operation == :number or operation == :variable
Unary.build operation, expr_tree[1]
else
Unary.build operation, build(expr_tree[1])
end
else
Binary.build operation, build(expr_tree[1]), build(expr_tree[2])
end
end
end
class Unary < Expr
def self.build(operation, argument)
case operation
when :sin then Sine.new argument
when :cos then Cosine.new argument
when :- then Negation.new argument
when :number then Number.new argument
when :variable then Variable.new argument
end
end
attr_reader :argument
def initialize(argument)
@argument = argument
end
def ==(other)
self.class == other.class and argument == other.argument
end
end
class Binary < Expr
def self.build(operation, left, right)
case operation
when :+ then Addition.new left, right
when :* then Multiplication.new left, right
end
end
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def ==(other)
self.class == other.class and
left == other.left and
right == other.right
end
end
class Addition < Binary
- def initialize(left, right)
- super
- end
-
def evaluate(environment = {})
left.evaluate(environment) + right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate + new_right.evaluate)
elsif new_left.exact? and new_left.evaluate == 0
new_right
elsif new_right.exact? and new_right.evaluate == 0
new_left
else
Addition.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
(Addition.new new_left, new_right).simplify
end
def to_s
"(#{left} + #{right})"
end
end
class Multiplication < Binary
- def initialize(left, right)
- super
- end
-
def evaluate(environment = {})
left.evaluate(environment) * right.evaluate(environment)
end
def exact?
left.exact? and right.exact?
end
def simplify
new_left, new_right = left.simplify, right.simplify
if new_left.exact? and new_right.exact?
Number.new (new_left.evaluate * new_right.evaluate)
elsif new_left.exact? and (new_left.evaluate == 1 or new_left.evaluate == 0)
new_left.evaluate == 1 ? new_right : Number.new(0)
elsif new_right.exact? and (new_right.evaluate == 1 or new_right.evaluate == 0)
new_right.evaluate == 1 ? new_left : Number.new(0)
else
Multiplication.new new_left, new_right
end
end
def derive(variable)
new_left = left.derive variable
new_right = right.derive variable
- left_mult = Multiplication.new new_left, right
- right_mult = Multiplication.new left, new_right
+ left_factor = Multiplication.new new_left, right
+ right_factor = Multiplication.new left, new_right
- (Addition.new left_mult, right_mult).simplify
+ (Addition.new left_factor, right_factor).simplify
end
def to_s
"(#{left} * #{right})"
end
end
class Number < Unary
- def initialize(argument)
- super
- end
-
def evaluate(environment = {})
argument
end
def exact?
true
end
def simplify
dup
end
def derive(variable)
Number.new 0
end
def to_s
"#{argument}"
end
end
class Variable < Unary
- def initialize(argument)
- super
- end
-
def evaluate(environment = {})
raise ArgumentError unless environment[argument]
environment[argument]
end
def exact?
false
end
def simplify
dup
end
def derive(variable)
argument == variable ? Number.new(1) : Number.new(0)
end
def to_s
"#{argument}"
end
end
class Negation < Unary
- def initialize(argument)
- super
- end
-
def evaluate(environment = {})
-(argument.evaluate environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (-new_argument.evaluate)
else
Negation.new new_argument
end
end
def derive(variable)
(Negation.new argument.derive(variable)).simplify
end
def to_s
"-#{argument}"
end
end
class Sine < Unary
- def initialize(argument)
- super
- end
-
def evaluate(environment = {})
Math.sin argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (Math.sin new_argument.evaluate)
else
Sine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Cosine.new(argument)).simplify
end
def to_s
"sin(#{argument})"
end
end
class Cosine < Unary
- def initialize(argument)
- super
- end
-
def evaluate(environment = {})
Math.cos argument.evaluate(environment)
end
def exact?
argument.exact?
end
def simplify
new_argument = argument.simplify
if new_argument.exact?
Number.new (Math.cos new_argument.evaluate)
else
Cosine.new new_argument
end
end
def derive(variable)
argument_derivative = argument.derive variable
(Multiplication.new argument_derivative, Negation.new(Sine.new(argument))).simplify
end
def to_s
"cos(#{argument})"
end
end