Skip to content

Instantly share code, notes, and snippets.

@danicuki
Created November 30, 2011 02:00
Show Gist options
  • Save danicuki/1407633 to your computer and use it in GitHub Desktop.
Save danicuki/1407633 to your computer and use it in GitHub Desktop.
Polinomio implementation in Scala (http://www.ime.usp.br/~reverbel/PFC-11/trabalhos/ep3/)
package pfc
private case class Term(coef: Double, exp: Int) {
require(coef != 0 && exp >= 0)
}
object Pol {
// conversao implicita de Double em Pol
implicit def doubleToPol(d: Double): Pol = Pol(d, 0)
// metodos de fabrica acessiveis para os clientes
def apply(coef: Double, exp: Int): Pol = {
if (coef == 0) new Pol(Nil)
else new Pol(new Term(coef, exp) :: Nil)
}
def apply(coef: Double): Pol = Pol(coef, 0)
// metodo de fabrica interno (serve apenas para evitar o uso de new)
private def apply(terms: List[Term]): Pol = new Pol(terms)
// metodo auxiliar para as operacoes de adicao e subtracao de polinomios
private def add(terms1: List[Term], terms2: List[Term]): List[Term] = {
if (terms1 == Nil) return terms2
if (terms2 == Nil) return terms1
if (terms1.head.exp > terms2.head.exp) return terms1.head :: add(terms1.tail, terms2)
if (terms1.head.exp < terms2.head.exp) return terms2.head :: add(terms1, terms2.tail)
else if (terms2.head.coef + terms1.head.coef != 0)
return Term(terms2.head.coef + terms1.head.coef, terms1.head.exp) :: add(terms1.tail, terms2.tail)
else
return add(terms1.tail, terms2.tail)
}
}
class Pol private (private val terms: List[Term]) {
// construtor auxiliar
// (n.b.: tanto o construtor primario como o auxiliar sao privados)
// private def this(coef: Double, exp: Int)
// aritmetica de polinomios
def +(that: Pol): Pol = Pol(Pol.add(this.terms, that.terms))
def -(that: Pol): Pol = this + (-that)
def *(that: Pol): Pol = {
terms.map(t => that * t).foldLeft(Pol(0))((acum, item) => acum + item)
}
def /(that: Pol): Tuple2[Pol, Pol] = {
if (that.degree > this.degree) return (Pol(0), this)
val partial = Pol(terms.first.coef / that.terms.first.coef, terms.first.exp - that.terms.first.exp)
val nextDividendo = this - (partial * that)
if (nextDividendo == Pol(0)) return (partial, Pol(0))
val nextDivide = (nextDividendo / that)
return (partial + nextDivide._1, nextDivide._2)
}
// operadores unarios
def unary_+ : Pol = this
def unary_- : Pol = Pol(terms.map(t => Term(-t.coef, t.exp)))
// aritmetica mista (o operando 1 e' um polinomio, o operando 2 e' um numero)
def +(d: Double): Pol = this + Pol(d)
def -(d: Double): Pol = this - Pol(d)
def *(d: Double): Pol = this * Pol(d)
def /(d: Double): Pol = (this / Pol(d))._1
// grau, potenciacao e derivacao
def degree: Int = terms.head.exp
def ^(n: Int): Pol = if (n == 0) Pol(1) else this * (this ^ (n - 1))
def deriv: Pol = {
terms.foldLeft(Pol(0))((acum, t) => acum + Pol(t.coef * t.exp, if (t.exp == 0) 0 else t.exp - 1))
}
def ! : Pol = deriv
// calcula o valor do polinomio alvo para um dado valor de x
def apply(x: Double): Double = {
terms./:(0.0) {
(acum, t) => acum + t.coef * BigDecimal.valueOf(x).pow(t.exp).toDouble
}
}
// composicao do polinomio alvo com outro polinomio
def apply(that: Pol): Pol = {
terms./:(Pol(0)) {
(acum, term) => acum + Pol(term.coef) * (that ^ term.exp)
}
}
// sobrescrita de metodos da classe Any
override def equals(other: Any): Boolean = (toString == other.toString)
// override def hashCode: Int
override def toString: String =
if (terms.isEmpty) "0" else terms.foldLeft("")((acum, term) => calcString(term, acum))
private def calcString(term: Term, acum: String): String = {
val sinal = if (term.coef < 0) "-" else "+"
val df = new java.text.DecimalFormat("#.################")
val valor = if (term.coef.abs == 1 && term.exp > 0) "" else df.format(term.coef.abs)
val letra = if (term.exp > 0) "x" else ""
val expo = if (term.exp >= 2) "^" + term.exp else ""
val pref =
if (acum == "")
if (sinal == "+") "" else "-"
else
" " + sinal + " "
(acum + pref + valor + letra + expo).trim()
}
// metodo auxiliar que multiplica o polinomio alvo por um termo simples
private def *(term: Term): Pol = {
Pol(terms.map(item => Term(term.coef * item.coef, term.exp + item.exp)))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment