Решение на Трета задача от Ивайло Христов

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

Към профила на Ивайло Христов

Резултати

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

Код

module Interpretator
# ======================
# Environment
# ======================
module Core #; end
end
class Number #; end
end
class Variable #; end
end
class Expression #; end
end
class Unary < Expression #; end
end
class Binary < Expression #; end
end
# ======================
# Parse data
# ======================
module PARSE
TYPES = {
:number => Interpretator::Number ,
:variable => Interpretator::Variable,
}
OPERATORS = {
:unary => {
:+ => Interpretator::Unary,
:- => Interpretator::Unary,
:sin => Interpretator::Unary,
:cos => Interpretator::Unary,
},
:binary => {
:+ => Interpretator::Binary,
:- => Interpretator::Binary,
:* => Interpretator::Binary,
}
}
end
# ======================
# Other data
# ======================
LENGTH_TO_OPERATOR_TYPE = {
2 => :unary ,
3 => :binary,
}
# ======================
# Builder
# ======================
def self.build(syntax_tree)
if PARSE::TYPES.has_key? syntax_tree.first
type = PARSE::TYPES[syntax_tree.first]
value = syntax_tree.last
return type.new(value)
end
operation = syntax_tree .fetch 0
operation_type = LENGTH_TO_OPERATOR_TYPE .fetch syntax_tree.length
operation_type_list = PARSE::OPERATORS .fetch operation_type
operation_class = operation_type_list .fetch operation
operands = syntax_tree.slice(1..-1).map {|operand| build operand}
operation_class.new operation, *operands
end
# ======================
# Core
# ======================
# common functionality for all the atoms ...
module Core
def evaluate(scope = {})
calculate(scope).value
end
def calculate(scope = {})
self
end
def simplify
self
end
end
# ======================
# Operators
# ======================
module BaseOperators
def -@
self.class.new self.value.send :-@
end
def +@
self.class.new self.value.send :+@
end
def +(other)
self.class.new self.value + other.value
end
def -(other)
self.class.new self.value - other.value
end
def *(other)
self.class.new self.value * other.value
end
end
module MathOperators
def sin
self.class.new Math.sin @value
end
def cos
self.class.new Math.cos @value
end
end
# ======================
# Variables
# ======================
class Variable
include Core
attr_reader :name
def initialize(name)
@name = name
end
def calculate(scope = {})
unless scope[@name]
throw 'Undefined variable "' + @name.to_s + '"'
end
Number.new scope[@name]
end
def derive(var)
Number.new var == @name ? 1 : 0
end
def ==(other)
other.class == self.class and
other.name == self.name
end
def to_s
@name.to_s
end
end
# ======================
# Types
# ======================
class Number
include Core
include BaseOperators
include MathOperators
attr_reader :value
def initialize(value)
@value = value
end
def derive(var)
self.class.new 0
end
def ==(other)
other.class == self.class and
other.value == self.value
end
def to_s
@value.to_s
end
end
# ======================
# Expressions
# ======================
class Expression
include Core
end
class Unary < Expression
attr_reader :operator, :operand
OPERATORS_MAP = {
:+ => :+@,
:- => :-@,
}
DERIVE_RULES = {
:+@ => lambda do |operand, var|
Unary.new(:+@, operand.derive(var)).simplify
end,
:-@ => lambda do |operand, var|
Unary.new(:-@, operand.derive(var)).simplify
end,
:sin => lambda do |operand, var|
Binary.new(:+, operand.derive(var), Unary.new(:cos, operand)).simplify
end,
:cos => lambda do |operator, var|
Binary.new(:+, operand.derive(var), Unary.new(:sin, operand)).simplify
end,
}
SIMPLIFICATIONS = {
:number => lambda do |expression|
return expression.calculate if expression.operand.is_a? Number
end,
:+ => lambda do |expression|
return expression.operand if expression.operator == :+
end,
}
def initialize(operator, operand)
@operator = OPERATORS_MAP.fetch operator, operator
@operand = operand
end
def ==(other)
other.class == self.class and
other.operator== self.operator and
other.operand == self.operand
end
def calculate(scope = {})
@operand.calculate(scope).send @operator
end
def simplify
SIMPLIFICATIONS.each do |name, try_to_simplify|
simplified = try_to_simplify.call(self)
return simplified.simplify if simplified
end
self.class.new @operator, @operand.simplify
end
def derive(var)
DERIVE_RULES[operator].call operand, var
end
def to_s
"#{operator.to_s}(#{operand.to_s})"
end
end
class Binary < Expression
attr_reader :operator, :left_operand, :right_operand
DERIVE_RULES = {
:+ => lambda do |left_operand, right_operand, var|
Binary.new(:+, left_operand.derive(var), right_operand.derive(var)).simplify
end,
:- => lambda do |left_operand, right_operand, var|
DERIVE_RULES[:+].call left_operand, Unary.new(:-, right_operand)
end,
:* => lambda do |left_operand, right_operand, var|
Binary.new(
:+,
Binary.new(:*, left_operand.derive(var), right_operand),
Binary.new(:*, left_operand, right_operand.derive(var)),
).simplify
end,
}
SIMPLIFICATIONS = {
:numbers => lambda do |expression|
return expression.calculate if
expression.left_operand .is_a? Number and
expression.right_operand.is_a? Number
end,
:variables => lambda do |expression|
return Number.new(0) if
expression.left_operand.is_a? Variable and
expression.left_operand == expression.right_operand and
expression.operator == :-
end,
:number_expression => lambda do |expression|
test_num = Number.new 13
left = expression.left_operand
right = expression.right_operand
unless left.is_a? Number and not right.is_a? Number
return
end
return case Binary.new( expression.operator, left, test_num ).calculate
when test_num then right
when left then left
end
end,
:expression_number => lambda do |expression|
return SIMPLIFICATIONS[:number_expression].call Binary.new(
expression.operator, expression.right_operand, expression.left_operand
)
end,
}
def initialize(operator, left_operand, right_operand)
@operator = operator
@left_operand = left_operand
@right_operand = right_operand
end
def ==(other)
other.class == self.class and
other.operator == self.operator and
other.left_operand == self.left_operand and
other.right_operand == self.right_operand
end
def calculate(scope = {})
@left_operand.calculate(scope).send @operator, @right_operand.calculate(scope)
end
def simplify
SIMPLIFICATIONS.each do |name, try_to_simplify|
simplified = try_to_simplify.call(self)
return simplified.simplify if simplified
end
simplified = self.class.new(
@operator,
@left_operand .simplify,
@right_operand.simplify,
)
if simplified == self then simplified else simplified.simplify end
end
def derive(var)
DERIVE_RULES[operator].call(left_operand, right_operand, var).simplify
end
def to_s
"(#{left_operand.to_s} #{operator.to_s} #{right_operand.to_s})"
end
end
end
Expr = Interpretator

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

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

Finished in 0.04999 seconds
13 examples, 0 failures

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

Ивайло обнови решението на 13.11.2012 11:13 (преди около 12 години)

+
+module Interpetator
+
+ # ======================
+ # Environment
+ # ======================
+
+ module Core #; end
+ end
+
+ class Number #; end
+ end
+ class Variable #; end
+ end
+
+ class Expression #; end
+ end
+ class Unary < Expression #; end
+ end
+ class Binary < Expression #; end
+ end
+
+ # ======================
+ # Parse data
+ # ======================
+
+ module PARSE
+ TYPES = {
+ :number => Interpetator::Number ,
+ :variable => Interpetator::Variable,
+ }
+
+ OPERATORS = {
+ :unary => {
+ :+ => Interpetator::Unary,
+ :- => Interpetator::Unary,
+ :sin => Interpetator::Unary,
+ :cos => Interpetator::Unary,
+ },
+
+ :binary => {
+ :+ => Interpetator::Binary,
+ :- => Interpetator::Binary,
+ :* => Interpetator::Binary,
+ }
+ }
+ end
+
+ # ======================
+ # Other data
+ # ======================
+
+ LENGTH_TO_OPERATOR_TYPE = {
+ 2 => :unary ,
+ 3 => :binary,
+ }
+
+ # ======================
+ # Builder
+ # ======================
+
+ def self.build(syntax_tree)
+ if PARSE::TYPES.has_key? syntax_tree.first
+ type = PARSE::TYPES[syntax_tree.first]
+ value = syntax_tree.last
+
+ return type.new(value)
+ end
+
+ operation = syntax_tree .fetch 0
+ operation_type = LENGTH_TO_OPERATOR_TYPE .fetch syntax_tree.length
+ operation_type_list = PARSE::OPERATORS .fetch operation_type
+ operation_class = operation_type_list .fetch operation
+
+ operands = syntax_tree.slice(1..-1).map {|operand| build operand}
+
+ operation_class.new operation, *operands
+ end
+
+ # ======================
+ # Core
+ # ======================
+
+ # common functionality for all the atoms ...
+
+ module Core
+ def evaluate(scope = {})
+ calculate(scope).value
+ end
+
+ def calculate(scope = {})
+ self
+ end
+
+ def simplify
+ self
+ end
+ end
+
+ # ======================
+ # Operators
+ # ======================
+
+ module BaseOperators
+ def -@
+ self.class.new self.value.send :-@
+ end
+
+ def +@
+ self.class.new self.value.send :+@
+ end
+
+ def +(other)
+ self.class.new self.value + other.value
+ end
+
+ def -(other)
+ self.class.new self.value - other.value
+ end
+
+ def *(other)
+ self.class.new self.value * other.value
+ end
+ end
+
+ module MathOperators
+ def sin
+ self.class.new Math.sin @value
+ end
+
+ def cos
+ self.class.new Math.cos @value
+ end
+ end
+
+ # ======================
+ # Variables
+ # ======================
+
+ class Variable
+ include Core
+
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def calculate(scope = {})
+ unless scope[@name]
+ throw 'Undefined variable "' + @name.to_s + '"'
+ end
+
+ Number.new scope[@name]
+ end
+
+ def derive(var)
+ Number.new var == @name ? 1 : 0
+ end
+
+ def ==(other)
+ other.class == self.class and
+ other.name == self.name
+ end
+
+ def to_s
+ @name.to_s
+ end
+ end
+
+ # ======================
+ # Types
+ # ======================
+
+ class Number
+ include Core
+ include BaseOperators
+ include MathOperators
+
+ attr_reader :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def derive(var)
+ self.class.new 0
+ end
+
+ def ==(other)
+ other.class == self.class and
+ other.value == self.value
+ end
+
+ def to_s
+ @value.to_s
+ end
+ end
+
+ # ======================
+ # Expressions
+ # ======================
+
+ class Expression
+ include Core
+ end
+
+ class Unary < Expression
+ attr_reader :operator, :operand
+
+ OPERATORS_MAP = {
+ :+ => :+@,
+ :- => :-@,
+ }
+
+ DERIVE_RULES = {
+ :+@ => lambda do |operand, var|
+ Unary.new(:+@, operand.derive(var)).simplify
+ end,
+
+ :-@ => lambda do |operand, var|
+ Unary.new(:-@, operand.derive(var)).simplify
+ end,
+
+ :sin => lambda do |operand, var|
+ Binary.new(:+, operand.derive(var), Unary.new(:cos, operand)).simplify
+ end,
+
+ :cos => lambda do |operator, var|
+ Binary.new(:+, operand.derive(var), Unary.new(:sin, operand)).simplify
+ end,
+ }
+
+ SIMPLIFICATIONS = {
+ :number => lambda do |expression|
+ return expression.calculate if expression.operand.is_a? Number
+ end,
+
+ :+ => lambda do |expression|
+ return expression.operand if expression.operator == :+
+ end,
+ }
+
+ def initialize(operator, operand)
+ @operator = OPERATORS_MAP.fetch operator, operator
+ @operand = operand
+ end
+
+ def ==(other)
+ other.class == self.class and
+
+ other.operator== self.operator and
+ other.operand == self.operand
+ end
+
+ def calculate(scope = {})
+ @operand.calculate(scope).send @operator
+ end
+
+ def simplify
+ SIMPLIFICATIONS.each do |name, try_to_simplify|
+ simplified = try_to_simplify.call(self)
+
+ return simplified.simplify if simplified
+ end
+
+ self.class.new @operator, @operand.simplify
+ end
+
+ def derive(var)
+ DERIVE_RULES[operator].call operand, var
+ end
+
+ def to_s
+ "#{operator.to_s}(#{operand.to_s})"
+ end
+ end
+
+ class Binary < Expression
+ attr_reader :operator, :left_operand, :right_operand
+
+ DERIVE_RULES = {
+ :+ => lambda do |left_operand, right_operand, var|
+ Binary.new(:+, left_operand.derive(var), right_operand.derive(var)).simplify
+ end,
+
+ :- => lambda do |left_operand, right_operand, var|
+ DERIVE_RULES[:+].call left_operand, Unary.new(:-, right_operand)
+ end,
+
+ :* => lambda do |left_operand, right_operand, var|
+ Binary.new(
+ :+,
+ Binary.new(:*, left_operand.derive(var), right_operand),
+ Binary.new(:*, left_operand, right_operand.derive(var)),
+ ).simplify
+ end,
+ }
+
+ SIMPLIFICATIONS = {
+ :numbers => lambda do |expression|
+ return expression.calculate if
+ expression.left_operand .is_a? Number and
+ expression.right_operand.is_a? Number
+ end,
+
+ :variables => lambda do |expression|
+ return Number.new(0) if
+ expression.left_operand .is_a? Variable and
+ expression.right_operand.is_a? Variable and
+ expression.operator == :-
+ end,
+
+ :number_expression => lambda do |expression|
+ test_num = Number.new 13
+ left = expression.left_operand
+ right = expression.right_operand
+
+ unless left.is_a? Number and not right.is_a? Number
+ return
+ end
+
+ return case Binary.new( expression.operator, left, test_num ).calculate
+ when test_num then right
+ when left then left
+ end
+ end,
+
+ :expression_number => lambda do |expression|
+ return SIMPLIFICATIONS[:number_expression].call Binary.new(
+ expression.operator, expression.right_operand, expression.left_operand
+ )
+ end,
+ }
+
+ def initialize(operator, left_operand, right_operand)
+ @operator = operator
+ @left_operand = left_operand
+ @right_operand = right_operand
+ end
+
+ def ==(other)
+ other.class == self.class and
+
+ other.operator == self.operator and
+ other.left_operand == self.left_operand and
+ other.right_operand == self.right_operand
+ end
+
+ def calculate(scope = {})
+ @left_operand.calculate(scope).send @operator, @right_operand.calculate(scope)
+ end
+
+ def simplify
+ SIMPLIFICATIONS.each do |name, try_to_simplify|
+ simplified = try_to_simplify.call(self)
+
+ return simplified.simplify if simplified
+ end
+
+ simplified = self.class.new(
+ @operator,
+ @left_operand .simplify,
+ @right_operand.simplify,
+ )
+ if simplified == self then simplified else simplified.simplify end
+ end
+
+ def derive(var)
+ DERIVE_RULES[operator].call(left_operand, right_operand, var).simplify
+ end
+
+ def to_s
+ "(#{left_operand.to_s} #{operator.to_s} #{right_operand.to_s})"
+ end
+ end
+end
+
+Expr = Interpetator

Ивайло обнови решението на 13.11.2012 20:21 (преди около 12 години)

-module Interpetator
+module Interpretator
# ======================
# Environment
# ======================
module Core #; end
end
class Number #; end
end
class Variable #; end
end
class Expression #; end
end
class Unary < Expression #; end
end
class Binary < Expression #; end
end
# ======================
# Parse data
# ======================
module PARSE
TYPES = {
- :number => Interpetator::Number ,
- :variable => Interpetator::Variable,
+ :number => Interpretator::Number ,
+ :variable => Interpretator::Variable,
}
OPERATORS = {
:unary => {
- :+ => Interpetator::Unary,
- :- => Interpetator::Unary,
- :sin => Interpetator::Unary,
- :cos => Interpetator::Unary,
+ :+ => Interpretator::Unary,
+ :- => Interpretator::Unary,
+ :sin => Interpretator::Unary,
+ :cos => Interpretator::Unary,
},
:binary => {
- :+ => Interpetator::Binary,
- :- => Interpetator::Binary,
- :* => Interpetator::Binary,
+ :+ => Interpretator::Binary,
+ :- => Interpretator::Binary,
+ :* => Interpretator::Binary,
}
}
end
# ======================
# Other data
# ======================
LENGTH_TO_OPERATOR_TYPE = {
2 => :unary ,
3 => :binary,
}
# ======================
# Builder
# ======================
def self.build(syntax_tree)
if PARSE::TYPES.has_key? syntax_tree.first
type = PARSE::TYPES[syntax_tree.first]
value = syntax_tree.last
return type.new(value)
end
operation = syntax_tree .fetch 0
operation_type = LENGTH_TO_OPERATOR_TYPE .fetch syntax_tree.length
operation_type_list = PARSE::OPERATORS .fetch operation_type
operation_class = operation_type_list .fetch operation
operands = syntax_tree.slice(1..-1).map {|operand| build operand}
operation_class.new operation, *operands
end
# ======================
# Core
# ======================
# common functionality for all the atoms ...
module Core
def evaluate(scope = {})
calculate(scope).value
end
def calculate(scope = {})
self
end
def simplify
self
end
end
# ======================
# Operators
# ======================
module BaseOperators
def -@
self.class.new self.value.send :-@
end
def +@
self.class.new self.value.send :+@
end
def +(other)
self.class.new self.value + other.value
end
def -(other)
self.class.new self.value - other.value
end
def *(other)
self.class.new self.value * other.value
end
end
module MathOperators
def sin
self.class.new Math.sin @value
end
def cos
self.class.new Math.cos @value
end
end
# ======================
# Variables
# ======================
class Variable
include Core
attr_reader :name
def initialize(name)
@name = name
end
def calculate(scope = {})
unless scope[@name]
throw 'Undefined variable "' + @name.to_s + '"'
end
Number.new scope[@name]
end
def derive(var)
Number.new var == @name ? 1 : 0
end
def ==(other)
other.class == self.class and
other.name == self.name
end
def to_s
@name.to_s
end
end
# ======================
# Types
# ======================
class Number
include Core
include BaseOperators
include MathOperators
attr_reader :value
def initialize(value)
@value = value
end
def derive(var)
self.class.new 0
end
def ==(other)
other.class == self.class and
other.value == self.value
end
def to_s
@value.to_s
end
end
# ======================
# Expressions
# ======================
class Expression
include Core
end
class Unary < Expression
attr_reader :operator, :operand
OPERATORS_MAP = {
:+ => :+@,
:- => :-@,
}
DERIVE_RULES = {
:+@ => lambda do |operand, var|
Unary.new(:+@, operand.derive(var)).simplify
end,
:-@ => lambda do |operand, var|
Unary.new(:-@, operand.derive(var)).simplify
end,
:sin => lambda do |operand, var|
Binary.new(:+, operand.derive(var), Unary.new(:cos, operand)).simplify
end,
:cos => lambda do |operator, var|
Binary.new(:+, operand.derive(var), Unary.new(:sin, operand)).simplify
end,
}
SIMPLIFICATIONS = {
:number => lambda do |expression|
return expression.calculate if expression.operand.is_a? Number
end,
:+ => lambda do |expression|
return expression.operand if expression.operator == :+
end,
}
def initialize(operator, operand)
@operator = OPERATORS_MAP.fetch operator, operator
@operand = operand
end
def ==(other)
other.class == self.class and
other.operator== self.operator and
other.operand == self.operand
end
def calculate(scope = {})
@operand.calculate(scope).send @operator
end
def simplify
SIMPLIFICATIONS.each do |name, try_to_simplify|
simplified = try_to_simplify.call(self)
return simplified.simplify if simplified
end
self.class.new @operator, @operand.simplify
end
def derive(var)
DERIVE_RULES[operator].call operand, var
end
def to_s
"#{operator.to_s}(#{operand.to_s})"
end
end
class Binary < Expression
attr_reader :operator, :left_operand, :right_operand
DERIVE_RULES = {
:+ => lambda do |left_operand, right_operand, var|
Binary.new(:+, left_operand.derive(var), right_operand.derive(var)).simplify
end,
:- => lambda do |left_operand, right_operand, var|
DERIVE_RULES[:+].call left_operand, Unary.new(:-, right_operand)
end,
:* => lambda do |left_operand, right_operand, var|
Binary.new(
:+,
Binary.new(:*, left_operand.derive(var), right_operand),
Binary.new(:*, left_operand, right_operand.derive(var)),
).simplify
end,
}
SIMPLIFICATIONS = {
:numbers => lambda do |expression|
return expression.calculate if
expression.left_operand .is_a? Number and
expression.right_operand.is_a? Number
end,
:variables => lambda do |expression|
return Number.new(0) if
- expression.left_operand .is_a? Variable and
- expression.right_operand.is_a? Variable and
+ expression.left_operand.is_a? Variable and
+ expression.left_operand == expression.right_operand and
expression.operator == :-
end,
:number_expression => lambda do |expression|
test_num = Number.new 13
left = expression.left_operand
right = expression.right_operand
unless left.is_a? Number and not right.is_a? Number
return
end
return case Binary.new( expression.operator, left, test_num ).calculate
when test_num then right
when left then left
end
end,
:expression_number => lambda do |expression|
return SIMPLIFICATIONS[:number_expression].call Binary.new(
expression.operator, expression.right_operand, expression.left_operand
)
end,
}
def initialize(operator, left_operand, right_operand)
@operator = operator
@left_operand = left_operand
@right_operand = right_operand
end
def ==(other)
other.class == self.class and
other.operator == self.operator and
other.left_operand == self.left_operand and
other.right_operand == self.right_operand
end
def calculate(scope = {})
@left_operand.calculate(scope).send @operator, @right_operand.calculate(scope)
end
def simplify
SIMPLIFICATIONS.each do |name, try_to_simplify|
simplified = try_to_simplify.call(self)
return simplified.simplify if simplified
end
simplified = self.class.new(
@operator,
@left_operand .simplify,
@right_operand.simplify,
)
if simplified == self then simplified else simplified.simplify end
end
def derive(var)
DERIVE_RULES[operator].call(left_operand, right_operand, var).simplify
end
def to_s
"(#{left_operand.to_s} #{operator.to_s} #{right_operand.to_s})"
end
end
end
-Expr = Interpetator
+Expr = Interpretator