Sederhanakan dan Ambil Derivatif Parsial ke String Polinomial

8

pengantar

Tulis program untuk menghitung turunan parsial dari polinomial (mungkin multivarian) berkenaan dengan variabel.

Tantangan

Derivatif adalah alat matematika yang sangat penting yang telah banyak diterapkan dalam fisika, kimia, biologi, ekonomi, psikologi dan banyak lagi untuk menangani semua jenis masalah. Ekspresi dengan banyak variabel juga sangat umum.

Dalam lingkup tantangan ini, string polinomial ("polystr") didefinisikan oleh BNF berikut (bentuk Backus-Naur):

<polystr> ::= <term> | <term><plusminus><polystr>

<plusminus> ::= "+" | "-"

<term> ::= <coeff> | <coeff><baseterm> | <baseterm>

<baseterm> ::= <variable> | <variable><exponent> | <baseterm><baseterm>

<coeff> ::= positive_integer

<exponent> ::= positive_integer

<variable> ::= lowercase_ASCII_letters

Di mana positive_integerdan lowercase_ASCII_letterscukup jelas.

Misalnya, String 3x2y-x3y-x2y+5berarti 3*(x^2)*y-(x^3)*y-(x^2)*y+5. Istilah yang diberikan dalam input dapat muncul dalam urutan apa pun, dan variabel dalam setiap istilah juga dapat muncul dalam urutan apa pun. Jadi misalnya 5-yx2-x3y+y3x2juga merupakan input yang valid dan sebenarnya sama dengan contoh sebelumnya.

Aturan untuk mengambil turunan parsial hanya melakukannya istilah demi istilah. Jika variabel yang muncul tidak muncul dalam istilah, turunannya adalah nol. Jika tidak, koefisien istilah dikalikan dengan eksponen variabel itu, dan kemudian eksponen variabel berkurang satu. Eksponen untuk variabel lain tidak berubah. Ini hanya mengikuti definisi dalam matematika. Selain itu, jika eksponen yang dihasilkan adalah nol, hapus variabel dari istilah tersebut.

Misalnya, untuk mengambil turunan parsial 5z-z2y2-5w3ysehubungan dengan y. Proses berikut ini dilakukan (sesuai dengan BNF yang didefinisikan di atas, "koefisien" semuanya dianggap bilangan positif, yaitu tanda-tanda dianggap secara terpisah)

          5z          -   z2y2        - 5w3y

Coeff                 1->1*2=2      5->5*1=5
Expon                 2->2-1=1      1->1-1=0
Term                  -   2yz2         - 5w3 
      (y is not here            (expon 0->y removed)
     so the term is 0)

Hasilnya adalah -2yz2-5w3y.

Di sisi lain, jika ungkapan di atas diambil sebagian turunan sehubungan dengan a, hasilnya adalah 0karena atidak ada ketentuan.

Tugas Anda adalah menulis fungsi atau program lengkap untuk menghitung turunan ini. Itu harus mengambil string polinomial dan satu karakter (variabel untuk mengambil turunan sehubungan dengan), dan mengembalikan turunan dalam bentuk paling sederhana.

"Bentuk paling sederhana" berarti tiga hal.

  1. Angka 0(bukan digit) tidak akan muncul dalam output kecuali jika output itu sendiri adil 0. Jadi output 0+10ytidak 3-y0zakan valid dan harus ditransformasikan ke 10ydan 3-z, masing-masing.

  2. Angka tersebut 1seharusnya tidak muncul sebagai eksponen atau koefisien, tetapi dapat muncul sebagai istilah yang berdiri sendiri.

  3. Istilah dengan himpunan variabel dan eksponen yang persis sama harus digabungkan, yang berarti 3a2b5-4b5a2bukan merupakan keluaran yang valid, dan seharusnya menjadi -a2b5gantinya. Informasi lebih lanjut tentang input dan output dapat ditemukan di bagian "Spesifikasi".

Uji Kasus

Input
Output

2xy+4ax-5+7mx4-4-7x4m, x
2y+4a

4upv+5u2v3w4-4w4u2v3+qr-v,v
4up+3u2v2w4-1

12ux-7x2m3+ab5,q
0

-a+10ca11y-1nv3rt3d-poly, a
-1+110ca10y

1y+1x3y, y
1+x3

Spesifikasi

  • Masukan dapat diambil melalui formulir standar . Dengan kata lain, Anda dapat mengambil input sebagai string, daftar karakter, array koefisien, variabel (mungkin dilambangkan dengan nilai ASCII dikurangi minus 'a' atau yang serupa) dan eksponen, dll. Anda juga bebas untuk mengubah string ke 2*x^3y^2atau sama, bukan 2x3y2.

Namun, tolong jangan gunakan input [2,0,0,0,1,0,0,3,0,0,...0](array dari 27 elemen) untuk istilah 2dg, atau format verbose lain yang menyebutkan 26 huruf seperti ini. Format input Anda juga harus dapat memperlakukan abdan basebagai input yang berbeda (sehingga format array 27-elemen tidak valid karena pembatasan ini juga).

  • Setiap variabel (huruf) hanya akan muncul sekali dalam setiap istilah input, itu berarti xxtidak akan muncul dan akan selalu disajikan sebagai x2, juga tidak akan sesuatu seperti a3b4a2muncul.

  • Untuk mengulangi, istilah dalam input dapat muncul dalam urutan apa pun.

  • Anda juga bebas memilih format output asalkan format verbose yang disebutkan di atas dihindari. Namun output harus selalu dalam bentuk paling sederhana seperti yang didefinisikan di atas. Sama seperti input, istilah dalam output dapat muncul dalam urutan apa pun, dan variabel dalam setiap istilah juga dapat muncul dalam urutan apa pun dan tidak harus konsisten di antara istilah. Itu artinya pu+2up2adalah output yang valid. Tanda untuk istilah terkemuka dapat berupa positif atau negatif dan -y+3xdan 3x-ykeduanya valid +3x-y.

  • Input selalu diberikan sedemikian rupa sehingga semua koefisien dan eksponen dalam output akan kurang dari 2 32 -1, atau bilangan bulat terbesar yang dapat ditangani bahasa Anda, mana yang lebih kecil. Mengklaim bahwa bilangan bulat terbesar yang dapat ditangani bahasa Anda terlalu kecil dan meremehkan tantangannya masuk dalam kategori celah default.

  • Ini adalah , jumlah byte terendah yang menang.

  • Seperti biasa, celah default berlaku di sini.

Sunting: Karena sebagian besar jawaban sejauh ini ternyata adalah internal yang melakukan seluruh tantangan, dan meskipun tahu ada builtin saya tidak punya niat untuk melarang internal seperti itu dari awal, saya juga tidak punya sekarang. Saya akan membuat kriteria kemenangan yang didasarkan pada basis per-bahasa, yaitu pengiriman dengan byte terkecil di setiap bahasa akan menang dalam bahasa itu. Saya akan menambahkan potongan standar untuk katalog jika ada cukup banyak pengiriman. Jangan ragu untuk mengirimkan kiriman bawaan untuk menunjukkan kekuatan bahasa Anda, tetapi jangan ragu untuk mengirimkan jawaban non-bawaan Anda meskipun itu jauh lebih lama dan bahasa Anda tidak memiliki bawaan. Selamat bermain golf kode dalam bahasa favorit Anda!

Weijun Zhou
sumber
@JonathanFrech Istilah kedua dan ketiga dalam input dapat digabungkan. Bersama-sama mereka memberikan istilah kedua dalam output.
Weijun Zhou
Ah, baiklah. Dalam contoh pertama Anda, mengapa -9muncul di output?
Jonathan Frech
1
Satu-satunya alasan Anda dapat menggabungkan output adalah karena input sudah dapat digabungkan. Itu membuat ini benar-benar kombinasi dari 2 masalah independen take derivativedanmerge
Ton Hospel
Saya berasumsi bentuk paling sederhana juga menyiratkan no exponent 1, meskipun Anda tampaknya tidak menyatakan ini
Ton Hospel
@ JonathanFrech Itu salah ketik. Tetap.
Weijun Zhou

Jawaban:

2

Python 2 , 252 245 byte

o,d=input()
D={};s=''
for c,t in o:T=`sorted(t)`;D[T]=D.get(T,0)+c
for t in D:
 c,t=D[t],dict(eval(t))
 if(d in t)*c:e=t[d];c*=e;t[d]=e-1;s+=('%+d '%c)[:~((-2<c<2)*sum(t.values())>0)]+''.join((v+`t[v]`*(t[v]>1))*(t[v]>0)for v in t)
print s or'0'

Cobalah online!

Mengambil input sebagai daftar koefisien dan persyaratan yang bersarang:

[
 [coeff1, [[var1_1,exp1_1],
           [var1_2,exp1_2],
           ... ]
 ],
 [coeff2, [[var2_1,exp2_1], ...]],
 ...
]

Misalnya, contoh pertama ( 5z-z2y2-5w3y) diberikan sebagai:

[
 [ 5, [['z', 1]          ] ], 
 [-1, [['z', 2], ['y', 2]] ],
 [-5, [['w', 3], ['y', 1]] ]
]

Footer berisi fungsi yang mem-parsing input string untuk format masukan yang diinginkan: parse(s).


Edit:

  • Mengambil input alih-alih fungsi
TFeld
sumber
2

Retina , 249 233 byte

(.)(?=.*¶\1$)
$&_
L`.\w*
G`_
^\b
+
%O`._?\d*
_\d+
*
\b[a-z]
1$&
\b(\d+)(?=.*?(_+))
$1*$2
O$`(.)_+(.+)
$2$1
+`((\+|-)_+)(.*)¶\2(_+\3)\b
$1$4
+`\+_(_*(.*)¶-)_(_*\2\b)
+$1$3
G`\b_
\b_+
$.&
_(__+)
$.1
^\+|¶|(.)__|._
$1
\b1([a-z])
$1
^$
0

Cobalah online! Tautan termasuk kasus uji. Penjelasan:

(.)(?=.*¶\1$)
$&_

Tambahkan _setelah setiap kemunculan variabel yang diberikan.

L`.\w*

Bagi input menjadi beberapa istilah.

G`_

Simpan hanya istilah yang mereferensikan variabel.

^\b
+

Awali a +jika istilah pertama tidak memiliki tanda.

%O`._?\d*

Sortir setiap istilah berdasarkan abjad. (Tandanya cocok, tapi itu tidak masalah; toh itu semacam di awal.)

_\d+
*

Ubah semua eksponen variabel menjadi unary.

\b[a-z]
1$&

Awali 1 sementara untuk istilah-istilah itu tanpa pengganda.

\b(\d+)(?=.*?(_+))
$1*$2

Lipat gandakan pengali dengan eksponen variabel, biarkan hasilnya dalam unary.

O$`(.)_+(.+)
$2$1

Sortir semua persyaratan.

+`((\+|-)_+)(.*)¶\2(_+\3)\b
$1$4

Tambahkan persyaratan dengan tanda yang sama.

+`\+_(_*(.*)¶-)_(_*\2\b)
+$1$3

Kurangi istilah tanda yang berbeda.

G`\b_

Hapus istilah yang dibatalkan dengan ketentuan tanda yang berbeda.

\b_+
$.&

Ubah pengganda kembali ke desimal.

_(__+)
$.1

Eksponen penurunan lebih besar dari tiga dan dikonversi kembali ke desimal.

^\+|¶|(.)__|._
$1

a) Hapus +tanda memimpin b) Gabungkan semua istilah kembali bersama-sama c) konversi kuadrat dari variabel ke variabel biasa d) hapus variabel jika tidak memiliki eksponen.

\b1([a-z])
$1

Hapus sementara 1 kecuali tidak punya apa-apa lagi untuk berkembang biak.

^$
0

Jika tidak ada istilah yang tersisa maka hasilnya adalah nol.

Mendukung istilah duplikat menghabiskan hampir setengah dari jumlah byte saya. Solusi 123 byte sebelumnya yang tidak menggunakan istilah deduplicate:

(.)(?=.*¶\1$)
$&_
L`.\w*
G`_
_\d+
*
\b[a-z]
1$&
\b(\d+)(?=.*?(_+))
$.($1*$2
_(__+)
$.1
^\+|¶|(.)__|._
$1
\b1([a-z])
$1
^$
0

Cobalah online! Penjelasan:

(.)(?=.*¶\1$)
$&_

Tambahkan _setelah setiap kemunculan variabel yang diberikan.

L`.\w*

Bagi input menjadi beberapa istilah.

G`_

Simpan hanya istilah yang mereferensikan variabel.

_\d+
*

Ubah semua eksponen variabel menjadi unary.

\b[a-z]
1$&

Awali 1 sementara untuk istilah-istilah itu tanpa pengganda.

\b(\d+)(?=.*?(_+))
$.($1*$2

Lipat gandakan pengali dengan eksponen variabel.

_(__+)
$.1

Eksponen penurunan lebih besar dari tiga dan dikonversi kembali ke desimal.

^\+|¶|(.)__|._
$1

a) Hapus +tanda memimpin b) Gabungkan semua istilah kembali bersama-sama c) konversi kuadrat dari variabel ke variabel biasa d) hapus variabel jika tidak memiliki eksponen.

\b1([a-z])
$1

Hapus sementara 1 kecuali tidak punya apa-apa lagi untuk berkembang biak.

^$
0

Jika tidak ada istilah yang tersisa maka hasilnya adalah nol.

Neil
sumber
Mengesankan, tetapi Anda harus menggabungkan kedua istilah itu dalam contoh TIO Anda.
Weijun Zhou
1
@ WeijunZhou Maaf, saya telah mengabaikan sedikit spek itu. Biarkan saya berpikir tentang hal itu ...
Neil
@ WeijunZhou Ugh, harganya terlalu banyak byte, tapi saya pikir saya sudah berhasil.
Neil
Terima kasih banyak atas kerja keras Anda yang mengesankan. Saya kira ini adalah poin yang baik bagi saya untuk mulai belajar Retina.
Weijun Zhou
1

Bahasa Wolfram (Mathematica) , 21 20 byte

-1 byte terima kasih kepada Jonathan Frech !

ToExpression@#~D~#2&

Cobalah online!

Input diformat sehingga setiap istilah mengikuti coeff * var1 ^ exp1 * var2 ^ exp2 .... Jika input dapat diambil sebagai ungkapan daripada string, solusinya adalah 1 byte: D.

notjagan
sumber
#1bisa #.
Jonathan Frech
0

Physica , 3 byte

Ini tidak menggunakan fitur baru apa pun. dan alternatif ASCII-nya saja, Differentiatetelah diperkenalkan lebih dari 10 hari yang lalu .

Demo

Diasumsikan bahwa ekspresi dan variabel dilewatkan sebagai string. Kode pengujian:

f = ∂

Print[f['2*x*y+4*a*x-5+7*m*x^4-4-7*x^4*m'; 'x']]
Print[f['4*u*p*v+5*u^2*v^3*w^4-4*w^4*u^2*v^3+q*r-v'; 'v']]
Print[f['-a+10*c*a^11*y-1*n*v^3*r*t^3*d-p*o*l*y'; 'a']]

Output yang tepat:

4*a + 2*y
4*p*u + 3*u**2*v**2*w**4 - 1
110*a**10*c*y - 1

Format ekspresi: *untuk multiplikasi, **untuk eksponensial, +dan -untuk penambahan dan pengurangan sesuai.

Physica - Demo Visual

Tuan Xcoder
sumber