8
\$\begingroup\$

Explanation

In this task you'll be given a set ofN points(x1,y1),…,(xN,yN) with distinctxi values and your task is to interpolate a polynomial through these points. If you know what Lagrange interpolation is you can skip this section.

The goal of apolynomial interpolation is to construct the (unique) polynomialp(x) with degreeN-1 (for higher degrees there are infinite solutions) for whichp(xi) = yi for alli = 1…N. One way to do so is to constructN Lagrange basis polynomials and form a linear combination. Such a basis polynomial is defined as follows:

                          l_i(x) := \cfrac{x-x_1}{x_i-x_1}\cdots\cfrac{x-x_{i-1}}{x_i-x_{i-1}}\cdot\cfrac{x-x_{i+1}}{x_i-x_{i+1}}\cdots\cfrac{x-x_N}{x_i-x_N}

As you can see if you evaluateli at the points x1,…,xi-1,xi+1,…,xN it is 0 by construction and 1 for xi, multiplying by yi will only change the value at xi and set it to yi. Now having N such polynomials that are 0 in every point except one we can simply add them up and get the desired result. So the final solution would be:

                                                        p(x) = \overset{N}{\underset{i=1}{\sum}} y_i \cdot l_i(x)

Challenge

  • the input will consist ofN data points in any reasonable format (list of tuples, Points, a set etc.)
  • the coordinates will all be of integer value
  • the output will be a polynomial in any reasonable format: list of coefficients, Polynomial object etc.
  • the output has to be exact - meaning that some solutions will have rational coefficients
  • formatting doesn't matter (2/2 instead of1 or1 % 2 for1/2 etc.) as long as it's reasonable
  • you won't have to handle invalid inputs (for example empty inputs or input wherex coordinates are repeated)

Testcases

These examples list the coefficients in decreasing order (for example[1,0,0] corresponds to the polynomialx2):

[(0,42)] -> [42][(0,3),(-18,9),(0,17)] -> undefined (you don't have to handle such cases)[(-1,1),(0,0),(1,1)] -> [1,0,0][(101,-42),(0,12),(-84,3),(1,12)] -> [-4911/222351500, -10116/3269875, 692799/222351500, 12]
askedDec 21, 2017 at 12:00
ბიმო's user avatar
\$\endgroup\$
1

3 Answers3

5
\$\begingroup\$

Pari/GP, 14 bytes

polinterpolate

Takes two lists[x1, ..., xn] and[y1, ..., yn] as input. Outputs a polynomial.

Try it online!


Pari/GP, 35 bytes, without built-in

f(x,y)=y/matrix(#x,,i,j,x[j]^(i-1))

Takes two lists[x1, ..., xn] and[y1, ..., yn] as input. Outputs a list of coefficients.

Try it online!

Neil's user avatar
Neil
184k12 gold badges76 silver badges290 bronze badges
answeredDec 21, 2017 at 12:36
alephalpha's user avatar
\$\endgroup\$
1
\$\begingroup\$

Enlist, 25 bytes

Ḣ‡ḟ¹‡,€-÷_Ḣ¥€§æc/§₱W€$↙·Ṫ

Try it online!


Monadic link takes an array of length 2 (e.g.,[[101,0,-84,1],[-42,12,3,12]]) as input. The first element of the array is list of x value, the second is list of y value. Output as list of coefficient in increasing degree.

Because @HyperNeutrino forgot to wrap numbers in rational wrapper if it is evaluated in list, (Try it online!) the argument must be hardcoded in the code.

The is necessary because HyperNeutrino make some mistake in implementing· I don't know (or is this a feature? Not sure)

Equivalent Mathematica code:

Expand[ Table[ Times @@ ((z - #)/(xi - #) & /@ DeleteCases[x, xi]) , {xi, x}] . y]

Try it online!

wherex andy are list of coordinates. This prints the polynomial.


What Enlist have for this challenge:

  • Built in rational number support
  • Convolutionæc (my feature request)
answeredDec 22, 2017 at 15:49
user202729's user avatar
\$\endgroup\$
1
  • 1
    \$\begingroup\$If you need a rational number version of Jelly,M might be worth a shot\$\endgroup\$CommentedDec 23, 2017 at 0:47
1
\$\begingroup\$

Python, withnumpy, 301 bytes

Seethis notebook for how it works.


Golfed version. 301 bytes, it can be golfed much more.Attempt this online!

import numpy as npfrom itertools import combinations as Cfrom numpy.polynomial import Polynomial as Pdef l(k,x):return P([sum([np.prod(x) for x in C(np.delete(x,k),i)])*(-1)**(i+1)/np.prod(np.delete(x,k)-x[k]) for i in range(len(x))][::-1])def f(x,y):return sum(l(k,x)*y[k] for k in range(len(y)))

Ungolfed version.Attempt this online!

import numpy as npfrom itertools import combinations from numpy.polynomial import Polynomial# get the Lagrange basis functiondef l(k, x):    n = len(x)    assert (k < len(x))        x_k = x[k]    x_copy = np.delete(x, k)        denominator = np.prod(x_copy - x_k)        coeff = []        for i in range(n):        coeff.append(sum([np.prod(x) for x in combinations(x_copy, i)]) * (-1)**(i+1) / denominator)        coeff.reverse()        return Polynomial(coeff)def f(x,y):return sum(l(k,x)*y[k] for k in range(len(y)))x=[101,0,-84,1]y=[-42,12,3,12]print(f"{l(0,x)=}\n")print(f"{l(1,x)=}\n")print(f"{l(2,x)=}\n")print(f"{l(3,x)=}\n")print("y[0]*l(0,x)+y[1]*l(1,x)+y[2]*l(2,x)+y[3]*l(3,x)== f(x):")print(f(x,y))
answeredOct 26, 2023 at 14:35
138 Aspen's user avatar
\$\endgroup\$

Your Answer

More generally…

  • …Please make sure to answer the question and provide sufficient detail.

  • …Avoid asking for help, clarification or responding to other answers (use comments instead).

Draft saved
Draft discarded

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.