Skip to content

Instantly share code, notes, and snippets.

@JohanLarsson
Last active August 29, 2015 13:56
Show Gist options
  • Save JohanLarsson/8977845 to your computer and use it in GitHub Desktop.
Save JohanLarsson/8977845 to your computer and use it in GitHub Desktop.
public class Polynom
{
public Polynom(params double[] coefficients)
{
Coefficients = coefficients;
}
public static Polynom Parse(string s)
{
var cs = new Dictionary<int, double>();
var reader = new PolynomReader(s);
if (reader.HasLeftSide)
reader.ReadLeftSide();
while (!reader.IsEos)
{
var sign = reader.ReadSign();
double c = reader.ReadCoefficient();
var i = reader.ReadDegree();
cs.Add(i, sign * c);
}
var coffs = new double[cs.Keys.Max() + 1];
foreach (var c in cs)
{
coffs[c.Key] = c.Value;
}
return new Polynom(coffs);
}
public double[] Coefficients { get; private set; }
public double CalcY(double x)
{
double y = 0;
for (int i = 0; i < Coefficients.Count(); i++)
{
y += Coefficients[i] * Math.Pow(x, i);
}
return y;
}
public override string ToString()
{
return ToString("n3");
}
public string ToString(int digits)
{
return ToString("n" + digits);
}
public string ToString(string format)
{
var sb = new StringBuilder();
sb.Append("y = ");
bool hasTerm = false;
for (int i = 0; i < Coefficients.Length; i++)
{
var c = Coefficients[i];
if (c == 0)
continue;
if (hasTerm)
{
if (c > 0)
sb.Append(" + ");
else
{
sb.Append(" - ");
}
}
else
{
if (c < 0)
sb.Append("-");
}
hasTerm = true;
if (Math.Abs(c) == 1 && i > 0)
{
sb.Append("x");
}
else if (i > 0)
{
sb.AppendFormat("{0} * x", Math.Abs(c).ToString(format));
}
switch (i)
{
case 0:
sb.Append(Math.Abs(c).ToString(format));
break;
case 1:
break;
default:
sb.AppendFormat("^{0}", i);
break;
}
}
return sb.ToString();
}
private class PolynomReader : StringReader
{
private StringBuilder sb = new StringBuilder();
public PolynomReader(string s)
: base(s)
{
if (string.IsNullOrEmpty(s))
throw new FormatException("Input string was not in a correct format.");
}
public void MoveToContent()
{
while (Peek() != -1 && char.IsWhiteSpace(PeekChar()))
{
base.Read();
}
}
public int ReadSign()
{
MoveToContent();
var c = PeekChar();
if (char.IsNumber(c) || c == 'x')
{
return 1;
}
if (c == '+')
{
base.Read();
return 1;
}
if (c == '-')
{
base.Read();
return -1;
}
throw new FormatException("Input string was not in a correct format.");
}
public double ReadDouble()
{
MoveToContent();
this.sb.Clear();
var c = PeekChar();
if (!char.IsNumber(c))
throw new FormatException("Input string was not in a correct format.");
while (char.IsNumber(c) || c == '.' || c=='e' || c=='E')
{
c = ReadChar();
sb.Append(c);
if (IsEos)
break;
c = PeekChar();
}
var value = double.Parse(sb.ToString(), CultureInfo.InvariantCulture);
sb.Clear();
return value;
}
public int ReadInt()
{
MoveToContent();
this.sb.Clear();
var c = PeekChar();
while (char.IsNumber(c))
{
c = ReadChar();
sb.Append(c);
if (IsEos)
break;
c = PeekChar();
}
var value = int.Parse(sb.ToString());
sb.Clear();
return value;
}
public int ReadDegree()
{
MoveToContent();
var c = PeekChar();
if (c == 'x')
{
Read();
MoveToContent();
c = PeekChar();
if (c != '^')
{
return 1;
}
Read();
return ReadInt();
}
if (c == '*')
{
Read();
MoveToContent();
c = PeekChar();
if (char.IsNumber(c) || c == 'x')
return ReadDegree();
throw new FormatException("Input string was not in a correct format.");
}
return 0;
}
public double ReadCoefficient()
{
MoveToContent();
var c = PeekChar();
if (c == 'x')
{
return 1;
}
return ReadDouble();
}
public bool IsEos
{
get
{
MoveToContent();
return Peek() == -1;
}
}
public void ReadLeftSide()
{
while (PeekChar() != '=' && Peek() != -1)
{
Read();
}
var c = ReadChar();
if (c == '=')
return;
throw new FormatException("Input string was not in a correct format.");
}
public bool HasLeftSide
{
get
{
MoveToContent();
return PeekChar() == 'y';
}
}
public char PeekChar()
{
return (char)base.Peek();
}
public char ReadChar()
{
return (char)base.Read();
}
}
}
public class PolynomTests
{
[TestCase(new double[] { 0, 1 }, "y = x")]
[TestCase(new double[] { 1, 1 }, "y = 1 + x")]
[TestCase(new double[] { -2, 1 }, "y = -2 + x")]
[TestCase(new double[] { 2, 2 }, "y = 2 + 2 * x")]
[TestCase(new double[] { 0, 0, 1 }, "y = x^2")]
[TestCase(new double[] { 0, 0, -1 }, "y = -x^2")]
[TestCase(new double[] { 1, 1, 1 }, "y = 1 + x + x^2")]
[TestCase(new double[] { 2, 2, 2 }, "y = 2 + 2 * x + 2 * x^2")]
[TestCase(new double[] { -1, -1, -1 }, "y = -1 - x - x^2")]
[TestCase(new double[] { -2, -2, -2 }, "y = -2 - 2 * x - 2 * x^2")]
public void ToStringTests(double[] coffs, string e)
{
var polynom = new Polynom(coffs);
Assert.AreEqual(e, polynom.ToString(0));
}
[TestCase("y = x", 0, 0)]
[TestCase("y = x", 1, 1)]
[TestCase("y = x", 2, 2)]
[TestCase("y = x", -2, -2)]
[TestCase("y = -x", 0, 0)]
[TestCase("y = -x", 2, -2)]
[TestCase("y = -x", -2, 2)]
[TestCase("y = 2 + x", 0, 2)]
[TestCase("y = 2 + 2 * x", 0, 2)]
public void CalcYTest(string ps, double x, double ey)
{
var polynom = Polynom.Parse(ps);
var y = polynom.CalcY(x);
Assert.AreEqual(ey, y);
}
[TestCase("y = x", new double[] { 0, 1 })]
[TestCase("y = x^2", new double[] { 0, 0, 1 })]
[TestCase("y = 1 + x", new double[] { 1, 1 })]
[TestCase("y = -2 + x", new double[] { -2, 1 })]
[TestCase("y = 2 + 2 * x", new double[] { 2, 2 })]
[TestCase("y = x^2", new double[] { 0, 0, 1 })]
[TestCase("y = -x^2", new double[] { 0, 0, -1 })]
[TestCase("y = 1 + x + x^2", new double[] { 1, 1, 1 })]
[TestCase("y = 2 + 2 * x + 2 * x^2", new double[] { 2, 2, 2 })]
[TestCase("y = -1 - x - x^2", new double[] { -1, -1, -1 })]
[TestCase("y = -2 - 2 * x - 2 * x^2", new double[] { -2, -2, -2 })]
[TestCase("y = -2.0 - 2.0 * x - 2.0 * x^2", new double[] { -2, -2, -2 })]
[TestCase("y = -2.0 - 2.0x - 2.0x^2", new double[] { -2, -2, -2 })]
[TestCase("y = - 2.0 * x - 2.0 - 2.0 * x^2", new double[] { -2, -2, -2 })]
[TestCase("y = - 2.0 * x - 2.0 - 2.0 * x^2.0", new double[] { -2, -2, -2 }, ExpectedException = typeof(FormatException))]
[TestCase("y = -2.0e-3 * x - 2.0 - 2.0 * x^2.0", new double[] { -0.002, -2, -2 }, ExpectedException = typeof(FormatException))]
[TestCase("y = x^2 +x^3", new double[] { 0, 0, 1, 1 })]
public void ParseTest(string s, double[] e)
{
var polynom = Polynom.Parse(s);
Assert.AreEqual(e.Length, polynom.Coefficients.Length);
for (int i = 0; i < e.Length; i++)
{
Assert.AreEqual(e[i], polynom.Coefficients[i]);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment