Polinom İnterpolasyonu


12

Gerçek keyfi hassas rasyonel sayılar kullanarak Polinom İnterpolasyonu yapan bir program yazın . Girdi şöyle görünür:

f (1) = 2/3
f (2) = 4/5
f (3) = 6/7
...

İşaretten önce ve sonra tam olarak bir boşluk olduğunu varsayabilirsiniz =, tüm sayılar kesir veya tamsayıdır. Ayrıca, girişteki tüm kesirlerin zaten indirgenemez olduğunu varsayabilirsiniz.

Hata kontrolüne gerek yoktur, girişin geçerli olduğunu ve f (x) 'de x'in iki katına çıkmadığını varsayabilirsiniz.

Çıktı LaTeX uyumlu bir formda olmalıdır, yayılan LaTeX kodu burada verilen çıktı ile aynı grafiksel temsili vermelidir.

f (x) = 123x ^ 2 + \ frac {45} {2} x + \ frac {7} {4}

Fraksiyon mümkün olduğunca azaltılmalıdır, örn. gibi bir şeye \frac{2}{4} izin verilmez. Sayı tamsayı ise, kesir kullanmayın.

Özel kurallar:

Programınız ...

  • derece 12'ye kadar polinomlar için çalışmak
  • makul giriş için 1 dakikadan daha kısa sürede
  • tüm hesaplamayı sizin için yapan herhangi bir işlev kullanmayın
  • mümkün olan en düşük derecede polinom çıkışı

testcases:

Verilen test senaryoları sadece açıklama amaçlıdır. Programınız tüm doğru girişler için doğru sonuç vermelidir.

Giriş

f (1) = 2/3
f (2) = 4/5
f (3) = 6/7

Çıktı

f (x) = - \ frac {4} {105} x ^ 2
       + \ frac {26} {105} x
       + \ frac {16} {35}

Giriş

f (-12) = 13/2
f (5/3) = 3/5
f (13) = -6
f (1/5) = -3/4

Çıktı

f (x) = - \ frac {2186133} {239455744} x ^ 3
       + \ frac {2741731} {149659840} x ^ 2
       + \ frac {26720517} {29201920} x
       - \ frac {279464297} {299319680}

Giriş

f (4/3) = 617/81
f (2) = 20/3
f (-8/3) = 6749/81
f (-5) = 7367/12
f (0) = 23/3

Çıktı

f (x) = \ frac {1} {2} x ^ 4
     - 2x ^ 3
     + \ frac {7} {4} x ^ 2
     + \ frac {23} {3}

Giriş

f (0) = 5
f (1) = 7
f (2) = 9
f (3) = 11
f (4) = 13

Çıktı

f (x) = 2x
     + 5

Giriş

f (1/2) = -1/2
f (-25) = -1/2
f (-54/12) = -1/2

Çıktı

f (x) = - \ frac {1} {2}

Şimdiye kadar kullandığınız tek şey rasyonel sayılarsa neden gerçek sayılardan bahsediyorsunuz?
Joey

Üzgünüm. İngilizcem zayıf. Evet, yalnızca rasyonel sayılar kullanın. Sonuçlar kesin olmak zorundadır.
FUZxxl

İlk test çantasında, dots ( ...) gerçekten girdinin bir parçası mı?
Eelvex

@Eelvex: Hayır. Sabit.
FUZxxl

Üçüncü test çantasının çıktısı yanlış. Doğru cevap -\frac{37745}{14592}x^4 - \frac{853249}{43776}x^3 + \frac{57809}{7296}x^2 + \frac{225205}{2736}x + \frac{23}{3}. Girişin farklı bir şey olması amaçlandığından şüpheleniyorum :)
Timwi

Yanıtlar:


3

J + sh

J kodu:

i=:0".(1!:1)3
i=:((-:#i),2)$i
c=:|.(%.(x:((i.#i)^~])"0({."1 i)))(+/ .*)(|:{:"1 i)
(":(-.0=c)#(c,.i.-#c))(1!:2)2

sh komut dosyası:

echo -n 'f(x) = '
tr -d 'f()=' | tr /\\n- r' '_  | ./polyint.ijs | sed -e 's/^/+/;s/_/-/;s/\([0-9]*\)r\([0-9]*\)/\\frac{\1}{\2}/;s/ \([0-9]*$\)/x^\1/;s/\^1//;s/x^0//;s/+\(.*-.*\)/\1/'

Sh komut dosyasını çalıştırın:

./pol-int.sh
f(1/2) = -1/2
f(-25) = -1/2
f(-54/12) = -1/2

f(x) = -\frac{1}{2}

.

./pol-int.sh
f(4/3) = 617/8
f(2) = 20/3
f(-8/3) = 6749/81
f(-5) = 7367/12
f(0) = 23/3

f(x) = -\frac{37745}{14592}x^4
       -\frac{853249}{43776}x^3
     +  \frac{57809}{7296}x^2
     + \frac{225205}{2736}x
     +  \frac{23}{3}

Aynı kaynak kodu biçimlendirmesini oluşturmanız gerekmez. LaTeX çıktısında. LaTeX'ten geçtikten sonra aynı grafiksel temsili vermelidir. Bazı karakterleri kaydetmek için çekinmeyin.
FUZxxl

J'yi okuyamıyorum, ancak kısa uzunluktan itibaren J'nin matris echelon formu için yerleşik bir işlevi olduğu anlamına mı geliyor?
Timwi

@Timwi: Hayır, ama yerleşik "ters matrisi" kullanıyorum. J çok gergin: "ters matris" uygulamak olsa bile, birkaç karakter uzunluğunda olurdu.
Eelvex

3

Perl (569 karakter)

use Math'BigInt;sub r{($u,$v)=@_;$v?r($v,$u%$v):$u}sub c{new Math'BigInt$_[0]}$a=@c=<>;for(@c){m!(-?\d+)/?(\d*). = (-?\d+)/?(\d*)!;$j{$_,$i}=$1**c$_,$k{$_,$i|=0}=($2||1)**c$_ for 0..$a;$j{$a,$i}=c$3;$k{$a,$i++}=c$4||1}for$p(0..$a-1){for$y(0..$p-1,$p+1..$a-1){$n=$j{$p,$y}*$k{$p,$p};$o=$k{$p,$y}*$j{$p,$p};$j{$_,$y}=$j{$_,$y}*$k{$_,$p}*$o-$k{$_,$y}*$j{$_,$p}*$n,$k{$_,$y}*=$k{$_,$p}*$o for 0..$a}}print"f(x)=";for(1..$a){$s=r$t=$j{$a,$p=$a-$_}*$k{$p,$p},$w=$k{$a,$p}*$j{$p,$p};$u=abs$t,print$t>0?"$z":'-',($z='+',$w/=$s)-1?"\\frac{$u}{$w}":$u,$p>1?"x^$p":x x$p if$t/=$s}

Detaylı açıklama:

use Math'BigInt;

# Subroutine to calculate gcd of two numbers
sub r{($u,$v)=@_;$v?r($v,$u%$v):$u}

# Subroutine to create BigInts
sub c{new Math'BigInt$_[0]}

# Read input
# Throughout, $a is the number of equations.
$a=@c=<>;

# Initialises the $a+1 × $a matrix with all the values.
# $j{$x,$y} contains the numerator, $k{$x,$y} the denominator.
for(@c)
{
    m!(-?\d+)/?(\d*). = (-?\d+)/?(\d*)!;

    # Puzzle for the reader: why is $i|=0 in the second one,
    # not the first one? Answer at the bottom!
    $j{$_,$i}=$1**c$_,$k{$_,$i|=0}=($2||1)**c$_ for 0..$a;
    $j{$a,$i}=c$3;
    $k{$a,$i++}=c$4||1
}

# Generates the matrix echelon form.
# Basically, it works like this:
for$p(0..$a-1)
{
    # For each element along the diagonal {$p,$p}, set all the values above and
    # below it to 0 by adding a multiple of row $p to each of the other rows.
    for$y(0..$p-1,$p+1..$a-1)
    {
        # So we need to multiply the row $p by the value of {$p,$y}/{$p,$p}
        # (stored in $n/$o) and then subtract that from row $y.
        $n=$j{$p,$y}*$k{$p,$p};
        $o=$k{$p,$y}*$j{$p,$p};
            $j{$_,$y}=$j{$_,$y}*$k{$_,$p}*$o-$k{$_,$y}*$j{$_,$p}*$n,
            $k{$_,$y}*=$k{$_,$p}*$o
        for 0..$a
    }
}

# Outputs the result
print"f(x)=";
for(1..$a)
{
    # Note this sets $p = $a-$_. $p is the power of x.
    # We need to divide {$a,$p} by {$p,$p}. Store the result in $t/$w.
    # We also need to put the fraction in lowest terms, so calculate the gcd.
    $s=r$t=$j{$a,$p=$a-$_}*$k{$p,$p},$w=$k{$a,$p}*$j{$p,$p};

    # Output this term only if the numerator ($t) is non-zero.
    # Output a plus sign only if this isn’t the first term.
    # Output a fraction only if the denomator ($w) isn’t 1.
        $u=abs$t,print$t>0?"$z":'-',
        ($z='+',$w/=$s)-1?"\\frac{$u}{$w}":$u,$p>1?"x^$p":x x$p
    if$t/=$s
}

# Answer to the puzzle buried in the code above:
# It’s because the second part is passed as a second argument to c,
# hence it is evaluated before the first part.

Yorumlar

  • Eminim bir kademe manipülasyon formu için bir fonksiyon sağlayan bir modül vardır. Özellikle bunu kullanmadım (bir tane bile aramadım) çünkü bu yarışmanın kendiniz yapmanın amacı olduğunu varsayıyorum. Bu şekilde de daha ilginç. Tabii ki BigInt için de aynı şey söylenebilir, ama sonra hiç kimsenin bu meydan okumayı denemeyeceğinden şüpheleniyorum ...

Düzenlemeler

  • (630 → 585) Gerçekleşti İki aşamalı yerine iki aşamalı bir döngü halinde yapabilirim. Açıklamaları kodda yorum olarak ekleyin.

  • (585 → 583) Sadece ben kullanmanızı sağlar paket sözdizimi keşfetti 'yerine ::.

  • (583 → 573) Biraz daha mikro golf

  • (573 → 569) Girişi ayrıştırmak için daha kısa düzenli ifade


Derleme hataları alıyorum: ideone.com/LoB2T
FUZxxl 21:11

@FUZxxl: Bunu işaret ettiğiniz için teşekkürler. Sadece eksik bir alan vardı. Şimdi düzeltildi.
Timwi

3

TI-Basic (83/84): 109 karakter

Teknik olarak 109 karakter, TI-Basic dim (, For (, ->, rref (, [A]) ve "tek karakter" olarak listeler.

Giriş, (x, y) çiftleri halinde L1 ve L2 olarak biçimlendirilir [ex L1 = (1,2,3,4), L2 = (2,3,5,7)].

{1,1}->dim([A]
{dim(L1),dim(L2)+1}->dim([A]
For(A,1,dim(L1)
For(B,dim(L1)-1,0,-1
L1(A)^B->[A](A,dim(L1)-B
End
L2(A->[A](A,dim(L1)+1
End
rref([A]->[A]
{0}->L3
For(A,1,dim(L1)
[A](A,dim(L1)+1->L3(A
End
Disp L3

1
Bu gerekçe veya LaTeX formu kullanmaz.
lirtosiast

1

Lagrange Yöntemi, Python, 199 bayt

Biraz geç ama ...

def lagrange(dp):
l = lambda i: lambda x: (prod([(x - dp[j][0]) / (dp[i][0] - dp[j][0]) for j in range(len(dp)) if i != j]))
return lambda x: sum([l(i)(x) * dp[i][1] for i in range(len(dp))])

1
Muhtemelen operatörlerin etrafındaki boşluklara ihtiyacınız yok, değil mi?

0
l=lambda D,i:lambda x:prod((x-Dj[0])/(D[i][0]-Dj[0])for j,Dj in enumerate(D)if i!=j)
L=lambda D:lambda x:sum(l(D,i)(x)*Di[1]for i,Di in enumerate(D))

Fred Freys kodunun kısaltılmış bir versiyonu. Birinin muhtemelen D'den l'e geçişini atlayabileceğine dikkat edin, çünkü sadece dış kapsamdan çekebilir. Muhtemelen burada benimle aynı şeyi yapabileceğiniz gibi, bir lambda bile tıraş edebiliriz. Bir gün test edeceğim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.