Skip to content

Instantly share code, notes, and snippets.

@fintara
Last active January 2, 2016 18:18
Show Gist options
  • Save fintara/8342157 to your computer and use it in GitHub Desktop.
Save fintara/8342157 to your computer and use it in GitHub Desktop.
Polynomial class makes possible to do simple operations like additions, subtractions and multiplications on polynomials.
<?php
/**
* Polynomial class makes possible to do simple operations like additions, subtractions and
* multiplications on polynomials.
*
* There are two ways to initiate a Polynomial object: from string or from array.
*
* @package fintara
* @author Tsvetan Ovedenski <[email protected]>
*/
namespace fintara;
class Polynomial {
private $_varLetter;
private $_coefficients = array();
/**
* @param char $varLetter
*/
public function __construct($varLetter = "x") {
if(strlen($varLetter) !== 1)
throw new \Exception("The variable letter should be only 1 character.");
$this->_varLetter = strtolower($varLetter);
}
/**
* Sets a polynomial from a string.
* Example format: x^3 + 2x - 3
* Whitespaces don't matter.
*
* @param string $polynomial
* @return Polynomial
*/
public function setFromString($polynomial) {
$polynomial = str_replace(" ", "", $polynomial);
$this->setCoefficientsFromString($polynomial);
return $this;
}
/**
* Sets a polynomial from an array.
*
* @param array $polynomial
* @return Polynomial
*/
public function setFromArray(array $polynomial) {
krsort($polynomial);
$this->_coefficients = $polynomial;
return $this;
}
/**
* Gets the coefficients from a string and sets them in the array.
*
* @param string $input
* @return void
*/
private function setCoefficientsFromString($input) {
$input = str_replace("-", "+-", $input);
$parts = explode("+", $input);
foreach ($parts as $part) {
if (preg_match("/[\d+]{$this->_varLetter}\^[\d+]/", $part)) {
list($coeff, $power) = explode("^", $part);
$this->_coefficients[(int) $power] = (int) str_replace($this->_varLetter, "", $coeff);
} else if (preg_match("/-{$this->_varLetter}\^[\d+]/", $part)) {
list($coeff, $power) = explode("^", $part);
$this->_coefficients[(int) $power] = -1;
} else if (preg_match("/{$this->_varLetter}\^[\d+]/", $part)) {
list($coeff, $power) = explode("^", $part);
$this->_coefficients[(int) $power] = 1;
}else if (preg_match("/[\d+]{$this->_varLetter}/", $part)) {
$this->_coefficients[1] = (int) str_replace($this->_varLetter, "", $part);
} else if($part === "-{$this->_varLetter}") {
$this->_coefficients[1] = -1;
} else if($part === $this->_varLetter) {
$this->_coefficients[1] = 1;
} else {
$this->_coefficients[0] = (int) $part;
}
}
for($i = 0; $i <= $this->getMaxDegree(); $i++) {
if(!isset($this->_coefficients[$i])) {
$this->_coefficients[$i] = 0;
}
}
}
/**
* @return array
*/
public function getCoefficients()
{
return $this->_coefficients;
}
/**
* Returns the max degree of the polynomial.
* @return integer
*/
public function getMaxDegree() {
ksort($this->_coefficients);
end($this->_coefficients);
$maxDegree = key($this->_coefficients);
reset($this->_coefficients);
return $maxDegree;
}
/**
* Returns the polynomial in a readable output.
* Example output: x^3+2x-1
*
* @param char $varLetter
* @return string
*/
public function getBeautifulOutput($varLetter = null) {
if(!$varLetter)
$varLetter = $this->_varLetter;
krsort($this->_coefficients);
$output = "";
$i = 0;
foreach($this->_coefficients as $power => $value) {
if($value !== 0) {
if(abs($value) !== 1 || $power === 0)
$output .= $value;
else if($value === -1)
$output .= "-";
if($value > 0 && $i !== 0)
$output .= "+";
if($power > 0) {
$output .= $varLetter;
if($power > 1)
$output .= "^{$power}";
}
}
$i++;
}
return $output;
}
/**
* Add a polynomial.
*
* @param Polynomial $polynomial
* @return Polynomial
*/
public function add(Polynomial $polynomial) {
$guestCoefficients = $polynomial->getCoefficients();
$maxDegree = max($polynomial->getMaxDegree(), $this->getMaxDegree());
for($i = 0; $i <= $maxDegree; $i++) {
if(!isset($guestCoefficients[$i])) {
$guestCoefficients[$i] = $this->_coefficients[$i];
} else if(isset($this->_coefficients[$i])) {
$guestCoefficients[$i] += $this->_coefficients[$i];
}
}
return (new Polynomial())->setFromArray($guestCoefficients);
}
/**
* Subtract a polynomial.
*
* @param Polynomial $polynomial
* @return Polynomial
*/
public function subtract(Polynomial $polynomial) {
$guestCoefficients = $polynomial->getCoefficients();
$thisCoefficients = $this->_coefficients;
$maxDegree = max($polynomial->getMaxDegree(), $this->getMaxDegree());
for($i = 0; $i <= $maxDegree; $i++) {
if(!isset($guestCoefficients[$i])) {
$thisCoefficients[$i] = 0 - $guestCoefficients[$i];
} else if(isset($guestCoefficients[$i])) {
$thisCoefficients[$i] -= $guestCoefficients[$i];
}
}
krsort($thisCoefficients);
return (new Polynomial())->setFromArray($thisCoefficients);
}
/**
* Multiply a polynomial.
*
* @param Polynomial $polynomial
* @return Polynomial
*/
public function multiply(Polynomial $polynomial) {
$guestCoefficients = $polynomial->getCoefficients();
$newCoefficients = array_fill(0, $this->getMaxDegree() + $polynomial->getMaxDegree() + 1, 0);
foreach($this->_coefficients as $tPower => $tValue) {
foreach($guestCoefficients as $gPower => $gValue) {
$tmpNewPower = $tPower + $gPower;
$newCoefficients[$tmpNewPower] += $tValue * $gValue;
}
}
return (new Polynomial())->setFromArray($newCoefficients);
}
}
$polynomA = (new Polynomial('x'))->setFromString('-x');
$polynomB = (new Polynomial('x'))->setFromString('x-1x^3');
echo $polynomA->getBeautifulOutput(); echo "\n";
echo $polynomB->getBeautifulOutput(); echo "\n\n";
echo $polynomA->multiply($polynomB)->getBeautifulOutput('y');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment