การแก้ไขพหุนาม


12

เขียนโปรแกรมที่ดำเนินการแก้ไขโพลิโนเมียล โดยใช้จำนวนตรรกยะที่เที่ยงตรงแม่นยำ อินพุตมีลักษณะดังนี้:

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

คุณอาจสมมติว่ามีช่องว่างหนึ่งช่องก่อนและหลัง=เครื่องหมายตัวเลขทั้งหมดเป็นเศษส่วนหรือจำนวนเต็ม คุณอาจจะคิดว่าเศษส่วนทั้งหมดในอินพุตนั้นลดลงไม่ได้

ไม่จำเป็นต้องทำการตรวจสอบข้อผิดพลาดคุณอาจสมมติว่าอินพุตนั้นถูกต้องและไม่มี x เพิ่มเป็นสองเท่าใน f (x)

เอาต์พุตควรอยู่ในรูปแบบที่เข้ากันได้กับ LaTeX รหัส LaTeX ที่ปล่อยออกมาควรให้การแสดงกราฟิกแบบเดียวกับเอาต์พุตที่ให้ไว้ที่นี่

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

เศษส่วนจะต้องลดลงให้ได้มากที่สุดเช่น สิ่งที่ชอบ\frac{2}{4} ไม่ได้รับอนุญาต หากตัวเลขเป็นจำนวนเต็มอย่าใช้เศษส่วน

กฎพิเศษ:

โปรแกรมของคุณควร ...

  • ทำงานให้กับชื่อพหุนามจนถึงระดับ 12
  • เสร็จสมบูรณ์ในเวลาน้อยกว่า 1 นาทีเพื่อการป้อนข้อมูลที่เหมาะสม
  • ไม่ใช้ฟังก์ชั่นใด ๆ ที่ทำการคำนวณทั้งหมดสำหรับคุณ
  • เอาท์พุทพหุนามระดับที่เล็กที่สุดที่เป็นไปได้

Testcases:

ชุดทดสอบที่ให้นั้นเป็นเพียงการชี้แจง โปรแกรมของคุณควรให้ผลลัพธ์ที่ถูกต้องสำหรับอินพุตที่ถูกต้องทั้งหมด

อินพุต

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

เอาท์พุต

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

อินพุต

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

เอาท์พุต

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

อินพุต

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

เอาท์พุต

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

อินพุต

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

เอาท์พุต

f (x) = 2x
     + 5

อินพุต

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

เอาท์พุต

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

ทำไมคุณพูดถึงจำนวนจริงถ้าสิ่งที่คุณเคยใช้เป็นตัวเลขที่มีเหตุผล?
Joey

ขอโทษ ภาษาอังกฤษของฉันไม่ดี ใช่ใช้ตัวเลขที่มีเหตุผลเท่านั้น ผลลัพธ์จะต้องมีความแน่นอน
FUZxxl

ใน testcase แรกมีจุด ( ...) เป็นส่วนหนึ่งของอินพุตจริงหรือไม่
Eelvex

@Eevenx: ไม่ แก้ไขแล้ว.
FUZxxl

ผลลัพธ์สำหรับ testcase ที่สามไม่ถูกต้อง คำตอบที่ถูกต้องคือ-\frac{37745}{14592}x^4 - \frac{853249}{43776}x^3 + \frac{57809}{7296}x^2 + \frac{225205}{2736}x + \frac{23}{3}คำตอบที่ถูกต้องคือฉันสงสัยว่าการป้อนข้อมูลที่ตั้งใจจะเป็นบางสิ่งบางอย่างที่แตกต่างกัน :)
Timwi

คำตอบ:


3

J + sh

สคริปต์ J:

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 สคริปต์:

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:

./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}

คุณไม่จำเป็นต้องสร้างการจัดรูปแบบซอร์สโค้ดที่แน่นอน ในเอาต์พุต LaTeX มันควรจะแสดงผลกราฟิกที่เหมือนกันหลังจากทำงานผ่าน LaTeX รู้สึกฟรีเพื่อบันทึกตัวอักษร
FUZxxl

ฉันอ่าน J ไม่ได้ แต่จากความยาวสั้น ๆ ฉันก็คิดว่า J มีฟังก์ชันในตัวสำหรับเมทริกซ์ echelon form?
Timwi

@Timwi: ไม่ แต่ฉันใช้ "inverse matrix" ในตัว J เป็นคำย่อมากแม้ว่าฉันจะใช้ "invert matrix" มันจะมีความยาวไม่กี่ตัวอักษร
Eelvex

3

Perl (569 ตัวอักษร)

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}

คำอธิบายโดยละเอียด:

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.

ความคิดเห็น

  • ฉันแน่ใจว่ามีโมดูลสำหรับการจัดการเมทริกซ์ที่มีฟังก์ชั่นสำหรับรูปแบบระดับ ฉันไม่ได้ใช้เฉพาะเจาะจง (ไม่แม้แต่จะค้นหา) เพราะฉันคิดว่ามันเป็นประเด็นของการประกวดครั้งนี้ที่จะทำด้วยตัวเอง มันเป็นวิธีที่น่าสนใจมากขึ้นเช่นกัน แน่นอนว่าสามารถพูดได้เหมือนกันเกี่ยวกับ BigInt แต่จากนั้นฉันสงสัยว่าจะไม่มีใครพยายามท้าทาย ...

การแก้ไข

  • (630 → 585) รู้จริงฉันสามารถทำแบบฟอร์มระดับในหนึ่งวงแทนสอง เพิ่มคำอธิบายเป็นความคิดเห็นในรหัส

  • (585 → 583)เพิ่งค้นพบไวยากรณ์แพคเกจที่ให้ผมใช้แทน'::

  • (583 → 573) Microgolfing บางอย่าง

  • (573 → 569)การแสดงออกปกติที่สั้นกว่าในการแยกวิเคราะห์อินพุต


ฉันได้รับข้อผิดพลาดในการรวบรวม: ideone.com/LoB2T
FUZxxl

@FZZxxl: ขอบคุณที่ชี้ให้เห็น มีพื้นที่ที่ขาดหายไป แก้ไขแล้ว
Timwi

3

TI-Basic (83/84): 109 ตัวอักษร

เทคนิค 109 ตัวอักษร TI-Basic นับสลัว (, สำหรับ (, ->, rref (, [A]) และแสดงรายการเป็น "หนึ่งตัวอักษร"

อินพุตถูกจัดรูปแบบเป็น L1 และ L2 ในคู่ (x, y) [อดีต 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
สิ่งนี้ไม่ได้ใช้แบบปันส่วนหรือแบบฟอร์ม LaTeX
lirtosiast

1

วิธีลากรองจ์, Python, 199 ไบต์

สายไปหน่อย แต่ ...

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
คุณอาจไม่ต้องการพื้นที่ว่างรอบตัวดำเนินการทั้งหมดใช่ไหม

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 รุ่นสั้นลง โปรดทราบว่าอาจข้ามผ่าน D ถึง l เนื่องจากสามารถดึงจากขอบเขตด้านนอกได้ ในขณะที่คุณสามารถทำเช่นเดียวกันกับฉันที่นี่เราสามารถโกนแลมบ์ดาหนึ่ง ฉันจะทดสอบมันสักวัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.