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:
2026-04-13 19:33:50 +03:00
parent f283d039c1
commit 1fff529e83
6 changed files with 221 additions and 99 deletions

View File

@@ -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|