implement interpreter and demo + bug fixes
- implement interpreter and demo - replace StandardError with appropriate subclasses - implement division - rewrite Polynomial.simplify()
This commit is contained in:
@@ -17,7 +17,7 @@ module RubyAlgebra
|
||||
|
||||
def to_s
|
||||
if @terms.empty?
|
||||
result = ''
|
||||
result = '0'
|
||||
else
|
||||
result = @terms[-1].to_s
|
||||
i = @terms.length - 2
|
||||
@@ -37,7 +37,7 @@ module RubyAlgebra
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def evaluate(values)
|
||||
def substitute(values)
|
||||
result = 0
|
||||
@terms.each do |term|
|
||||
# ...
|
||||
@@ -67,6 +67,50 @@ module RubyAlgebra
|
||||
end
|
||||
end
|
||||
|
||||
def /(other)
|
||||
raise StandardError, "cannot divide by zero" if other.zero?
|
||||
return [Polynomial.new, Polynomial.new] if self.zero?
|
||||
|
||||
# Сначала проверить, что оба многочлена от одной и той же переменной
|
||||
t = if @terms.empty? || @terms[-1].variables.empty? then other.terms[-1] else @terms[-1] end
|
||||
unless t.variables.empty?
|
||||
only_variable = t.variables.keys[0]
|
||||
@terms.each do |term|
|
||||
next if term.variables.empty?
|
||||
unless term.variables.length == 1 && term.variables.keys[0] == only_variable
|
||||
raise StandardError, "cannot divide polynomials with different variables"
|
||||
end
|
||||
end
|
||||
other.terms.each do |term|
|
||||
next if term.variables.empty?
|
||||
unless term.variables.length == 1 && term.variables.keys[0] == only_variable
|
||||
raise StandardError, "cannot divide polynomials with different variables"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
quotient = Polynomial.new
|
||||
remainder = self
|
||||
divisor_power = unless other.terms.last.variables.empty? then other.terms.last.variables.first[1] else 0 end
|
||||
loop do
|
||||
break if remainder.zero?
|
||||
|
||||
dividend_power = unless remainder.terms.last.variables.empty? then remainder.terms.last.variables.first[1] else 0 end
|
||||
break if dividend_power < divisor_power
|
||||
|
||||
result_power = dividend_power - divisor_power
|
||||
result_coeff = remainder.terms.last.coeff.to_f / other.terms.last.coeff
|
||||
if result_power > 0
|
||||
q = Term.new(result_coeff, {only_variable => result_power})
|
||||
else
|
||||
q = Term.new(result_coeff, {})
|
||||
end
|
||||
quotient += q
|
||||
remainder -= other * q
|
||||
end
|
||||
[quotient, remainder]
|
||||
end
|
||||
|
||||
def **(other)
|
||||
result = Polynomial.new([Term.new(1)])
|
||||
other.times do
|
||||
@@ -91,50 +135,40 @@ module RubyAlgebra
|
||||
@terms == other.terms
|
||||
end
|
||||
|
||||
def simplify
|
||||
def _simplify
|
||||
i = 0
|
||||
new_terms = @terms.filter { |t| !t.zero? }
|
||||
while i < new_terms.length
|
||||
j = i + 1
|
||||
annihilated = false
|
||||
while j < new_terms.length
|
||||
if new_terms[i].similar_to?(new_terms[j])
|
||||
new_terms[i] += new_terms[j]
|
||||
new_terms.delete_at(j)
|
||||
if new_terms[i].zero?
|
||||
new_terms.delete_at(i)
|
||||
i -= 1
|
||||
j -= 1
|
||||
annihilated = true
|
||||
break
|
||||
end
|
||||
new_terms.delete_at(j)
|
||||
j -= 1
|
||||
else
|
||||
j += 1
|
||||
end
|
||||
j += 1
|
||||
end
|
||||
i += 1
|
||||
i += 1 unless annihilated
|
||||
end
|
||||
Polynomial.new(new_terms.sort_by { |t| t.total_power })
|
||||
new_terms.sort_by { |t| t.total_power }
|
||||
end
|
||||
|
||||
def simplify
|
||||
Polynomial.new(_simplify)
|
||||
end
|
||||
|
||||
def simplify!
|
||||
i = 0
|
||||
new_terms = @terms.filter { |t| !t.zero? }
|
||||
while i < new_terms.length
|
||||
j = i + 1
|
||||
while j < new_terms.length
|
||||
if new_terms[i].similar_to?(new_terms[j])
|
||||
new_terms[i] += new_terms[j]
|
||||
if new_terms[i].zero?
|
||||
new_terms.delete_at(i)
|
||||
i -= 1
|
||||
j -= 1
|
||||
end
|
||||
new_terms.delete_at(j)
|
||||
j -= 1
|
||||
end
|
||||
j += 1
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
@terms = new_terms.sort_by { |t| t.total_power }
|
||||
@terms = _simplify
|
||||
end
|
||||
|
||||
def zero?
|
||||
@terms.all? { |t| t.zero? }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -160,7 +194,7 @@ module RubyAlgebra
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def evaluate(values)
|
||||
def substitute(values)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
@@ -186,6 +220,11 @@ module RubyAlgebra
|
||||
Term.new(@coeff * other.coeff, new_variables)
|
||||
end
|
||||
|
||||
def /(other)
|
||||
raise StandardError, "cannot divide by zero" if other.zero?
|
||||
|
||||
end
|
||||
|
||||
def +@
|
||||
Term.new(@coeff, @variables)
|
||||
end
|
||||
@@ -203,7 +242,13 @@ module RubyAlgebra
|
||||
end
|
||||
|
||||
def to_s
|
||||
result = @coeff != 1 ? @coeff.to_s : ''
|
||||
if @coeff == 1 && !@variables.empty?
|
||||
result = ''
|
||||
elsif @coeff == -1 && !@variables.empty?
|
||||
result = '-'
|
||||
else
|
||||
result = @coeff.to_s
|
||||
end
|
||||
unless @variables.empty?
|
||||
first = true
|
||||
@variables.each do |var, power|
|
||||
|
||||
Reference in New Issue
Block a user