20
1
Challenge: I want to know about the real roots of polynomials. As a pure mathematician, I care about the existence of such roots, rather than their numeric values.
The challenge is to write the shortest program that takes a polynomial, of degree at most 4, and simply returns how many distinct real roots said polynomial has. Polynomials with degree 4 or less have the unique property that there exist closed forms (such as the quadratic formula), which give all their roots. You can google these forms or find some useful related information in the appendix.
Input: the coefficients of a polynomial. For simplicity, we shall only care about polynomials with integer coefficients.
You may input this as a list, get the coefficients one at a time, or use any other reasonable method. You may, for example, require polynomials of degree d to inputted as lists of length d+1.
You should specify how you convert a polynomial of degree at most 4 into a valid input.
Output: the number of distinct real roots of said polynomial. (meaning roots with multiplicity are only counted once)
You must output one of the integers 0,1,2,3,4 for valid polynomials, and trailing spaces are completely fine. (the special case of the polynomial, \$P(x) = 0\$, is discussed in the scoring section)
Examples: in these examples, we represent a polynomial, \$P\$, as a list L, where L[i]
contains the coefficient of \$x^i\$ in \$P\$. (with index starting at 0)
\$P(x) = 1\$, input: [1], output: 0
\$P(x) = 1+2x\$, input: [1,2], output: 1
\$P(x) = 1+x^2\$, input: [1,0,1], output: 0
\$P(x) = 1+x+x^2+x^3 = (x+1)(1+x^2)\$, input: [1,1,1,1], output: 1
\$P(x) = 2+3x+x^2 = (x+2)(x+1)\$, input: [2,3,1], output: 2
\$P(x) = 1-2x+x^2 = (x-1)^2\$, input: [1,-2,1], output: 1
Scoring:
-5 bytes if the polynomial, \$P(x) = 0\$, outputs a representation of infinity, such as: the infinity float in python, the Unicode symbol ∞
, or a string that can be mathematically interpreted to evaluate to infinity, like "1/0". (otherwise, you don't need to handle this case)
Otherwise, shortest code wins. (however I am personally quite interested in seeing answers which don't rely on built-in root finders)
Appendix: Closed Forms
Starting with the basics:
Degree 0: \$P(x) = a\$, roots: none, (or all reals, if a = 0)
Degree 1: \$P(x) = ax+b\$, roots: \$x=-b/a\$
Degree 2: \$P(x) = ax^2+bx+c\$, roots: \$x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}\$
Then, we have the harder ones. For these, it becomes quite verbose to state the closed forms. I've paraphrased some ways you can deduce the number of roots by considering discriminants, you may also seek to find the closed forms of the roots.
Degree 3: From Wikipedia. \$ P(x) = ax^3+bx^2+cx+d\$. We define the discriminant as \$\Delta = 18abcd -4b^3d+b^2d^2-4ac^3-27a^3d^2\$.
If \$\Delta > 0\$ then there are 3 distinct roots, if \$\Delta = 0\$, then there are two distinct real roots, otherwise then \$ \Delta < 0\$ and there is only one real root.
Degree 4: From Wikipedia.\$ P(x) = ax^4+bx^3+cx^2+dx+e\$. We define the discriminant as $$\begin{align} \Delta\ =\ &256 a^3 e^3 - 192 a^2 b d e^2 - 128 a^2 c^2 e^2 + 144 a^2 c d^2 e - 27 a^2 d^4 \\ &+ 144 a b^2 c e^2 - 6 a b^2 d^2 e - 80 a b c^2 d e + 18 a b c d^3 + 16 a c^4 e \\ &- 4 a c^3 d^2 - 27 b^4 e^2 + 18 b^3 c d e - 4 b^3 d^3 - 4 b^2 c^3 e + b^2 c^2 d^2 \end{align}$$
If \$\Delta > 0\$ then there are two distinct real roots. Otherwise things get more complicated.
Defining \$P = 8ac - 3b^2\$, \$D = 64 a^3 e - 16 a^2 c^2 + 16 a b^2 c - 16 a^2 bd - 3 b^4\$, then if \$ \Delta < 0 \$ and \$ P < 0\$ and \$ D < 0 \$ then there are 4 distinct real roots. Otherwise, if \$ \Delta < 0\$, there are 2 distinct real roots.
Finally, if \$\Delta = 0\$, we define \$\Delta_0=c^2-3bd+12ae\$ and \$R= b^3+8da^2-4abc\$.
If \$D =0\$, then:
- \$ P < 0\$ implies two distinct real roots
- \$ P > 0\$ implies zero distinct real roots
- \$P = 0\$ implies four distinct real roots
Else, if \$\Delta_0 = 0\$, then there are two distinct real roots.
Else, if \$P<0\$ and \$D <0\$ there are three distinct real roots.
Else, there are one real root.
Is it not possible for polys of degree 5? – Anush – 2020-02-26T09:11:02.043
2@Anush The polynomial $x^5-x+1$ is an example of a polynomial with a root which cannot be expressed with radicals. (instead, we need hypergeometric functions) Since the roots no longer have a nice expression, we can't get an easy closed form, making considering higher degrees much less simple. – Zachary Hunter – 2020-02-26T09:23:39.493
@Grimmy, yeah, I'll fix that. – Zachary Hunter – 2020-02-26T09:25:43.843
OK but we could still ask them to find the number of roots right? They just can't do it via the radical root. – Anush – 2020-02-26T09:30:44.220
@Anush, I'm also interested in programs that don't use built-in functions. To the best of my knowledge, this is only feasible with the restriction of degree, unless you use much deeper and complicated math formulas, or you repeat the premise of https://codegolf.stackexchange.com/questions/11694/find-real-roots-of-a-polynomial?rq=1.
– Zachary Hunter – 2020-02-26T10:01:10.863@Anush On the other hand, finding rational roots of a polygon of integer coefficients is trivial for arbitrary degree. – Neil – 2020-02-26T10:52:21.550
I suggest you add an example with mixed (real and complex) roots, such as
[1, 0, 3, 1]
, which has 1 real root and 2 complex roots. – agtoever – 2020-02-26T15:10:44.250@ZacharyHunter: if you are specifically interested in non-built-in solutions, maybe next time consider another challange than #codegolf, which more or less encourages us to use built-ins... – agtoever – 2020-02-26T15:12:42.280
1@Neil How is trivial? – Anush – 2020-02-26T17:05:55.937
1
@Anush https://en.m.wikipedia.org/wiki/Rational_root_theorem
– Grimmy – 2020-02-26T18:36:06.5501
For the record, "count the number of roots in an interval" is a task that does not require being able to write down the roots; Sturm's theorem is a bit technical to explain, but it is a simple algorithm to count the number of roots of a polynomial over an interval (or over the whole real line) (and this is used in the answers)
– Milo Brandt – 2020-02-26T23:31:33.8331I'm wondering if a golfy approach here would be to evaluate the polynomial at a huge number of equally spaced points, and count the intervals where it crosses zero or nearly touches it. This would require a mesh size small enough to separate any two roots, and an epsilon where anything approaching that close to an axis must actually be multiple root touching it. I suspect something suitably small in the polynomial degree and coefficients will suffice, but don't now how to prove it. – xnor – 2020-02-27T04:12:27.560