多項式文字列への偏微分を簡略化して取得する


8

前書き

変数に関する多項式(多変量の場合もある)の偏微分を計算するプログラムを記述します。

チャレンジ

デリバティブは、物理学、化学、生物学、経済学、心理学など、あらゆる種類の問題を処理するために広く適用されている非常に重要な数学的ツールです。複数の変数を持つ式も非常に一般的です。

この課題の範囲では、多項式文字列(「polystr」)は次のBNF(バッカスナウア形式)によって定義されます。

<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

どこにpositive_integerlowercase_ASCII_letters非常に自明です。

たとえば、文字列3x2y-x3y-x2y+5はを意味し3*(x^2)*y-(x^3)*y-(x^2)*y+5ます。入力で指定された用語は任意の順序で表示され、各用語の変数も任意の順序で表示されます。したがって、たとえば、これ5-yx2-x3y+y3x2も有効な入力であり、実際には前の例と同じです。

偏微分を取るためのルールは、期間ごとに行うことです。変数が出現し、用語に出現しない場合、導関数はゼロです。それ以外の場合は、項の係数にその変数の指数が乗算され、変数の指数が1つ減少します。他の変数の指数は変化しません。これはちょうど数学の定義に従っています。さらに、結果の指数がゼロの場合は、項から変数を削除します。

たとえば5z-z2y2-5w3y、に関するの偏微分を取得する場合y。次のプロセスが実行されます(上記で定義されたBNFに従って、「係数」はすべて正の数であると見なされます。つまり、符号は個別に考慮されます)。

          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)

結果は-2yz2-5w3yです。

一方、上記の式をに関して偏微分したa場合、結果はの項にない0ためaです。

あなたの仕事は、この導関数を計算するための関数または完全なプログラムを書くことです。これは、多項式文字列と単一の文字(微分に関して取る変数)を取り、微分を最も単純な形式で返す必要があります。

「最も単純な形式」とは、3つのことを意味します。

  1. 0(数字ではなく)番号は、出力自体がでない限り、出力に表示されません0。したがって、0+10yもも3-y0z有効な出力ではなく、それぞれ10y3-zに変換する必要があります。

  2. 数値1は、指数や係数として表示されるべきではありませんが、単独の項として表示されます。

  3. 変数と指数のセットがまったく同じ用語はマージ3a2b5-4b5a2する必要があり-a2b5ます。つまり、これは有効な出力ではなく、代わりにマージする必要があります。入力と出力の詳細については、「仕様」セクションをご覧ください。

テストケース

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

スペック

  • 入力は、標準フォームを介して取得できます。つまり、文字列、文字のリスト、係数のネストされた配列、変数(ASCII値から「a」を引いたものなどで示される場合があります)、および指数などの入力を取ることができます。また、自由に変更することもできます。の2*x^3y^2代わりに、またはに似た文字列2x3y2

ただし、の入力[2,0,0,0,1,0,0,3,0,0,...0](27要素の配列)2dgや、このような26文字を列挙するその他の詳細形式は使用しないでください。あなたの入力フォーマットはまた、治療することができなければならないabba(27素子アレイフォーマットは、この制限に起因も無効になるように)異なる入力として。

  • 各変数(文字)は、入力の各項に1回だけ表示されます。つまり、xx表示されx2ず、常にとして表示されることもありませんa3b4a2

  • 繰り返しになりますが、入力内の用語は任意の順序で現れることがあります。

  • また、上記の冗長形式を避ければ、出力形式を自由に選択できます。ただし、出力は常に上記で定義した最も単純な形式である必要があります。入力と同様に、出力の項は任意の順序で表示でき、各項の変数も任意の順序で表示でき、用語間で一貫している必要はありません。つまりpu+2up2、有効な出力です。先行用語の符号は正または負のいずれかで-y+3xあり3x-y、両方とも有効です+3x-y。そうです。

  • 入力は常に、出力のすべての係数と指数が2 32 -1か、言語が処理できる最大の整数のいずれか小さい方になるように指定されます。言語が処理できる最大の整数は不当に小さく、挑戦を簡単にすることはデフォルトの抜け穴の範疇に入ります。

  • これはであり、最小のバイト数が優先されます。

  • いつものように、デフォルトの抜け穴がここに適用されます。

編集:これまでの答えのほとんどは、全体の挑戦を行う内部であることが判明しているため、組み込みが存在することを知っていても、そのような内部を最初から禁止するつもりはありませんし、現在もそうではありません。受賞基準は言語ごとに基づいたものにします。つまり、各言語でバイト数が最も少ない送信がその言語で勝ちます。十分な提出がある場合は、カタログの標準スニペットを追加します。あなたの言語の力を紹介するためにビルトインを提出することを遠慮なく行ってください。しかし、それがはるかに長く、あなたの言語にビルトインがない場合でも、あなたの非組み込みの回答を提出することを躊躇しないでください。あなたの好きな言語でハッピーコードゴルフ!


@JonathanFrech入力の2番目と3番目の項をマージできます。それらは一緒に出力の2番目の項を与えます。
Weijun Zhou

うん、いいよ。最初の例では、なぜ-9出力に表示されるのですか?
Jonathan Frech、2018

1
出力でマージできる唯一の理由は、入力がすでにマージされている可能性があるためです。本当にこの2つの独立した問題の組み合わせになりそれtake derivativemerge
トンHospel

no exponent 1あなたはこれを述べていないように見えますが、私は最も単純な形もを意味すると思います
トンホスペル

@JonathanFrechそれはタイプミスです。修繕。
Weijun Zhou

回答:


2

パイソン2252の 245バイト

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'

オンラインでお試しください!

係数と項のネストされたリストとして入力を受け取ります。

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

たとえば、最初の例(5z-z2y2-5w3y)は次のようになります。

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

フッターには、文字列入力を目的の入力形式に解析する関数が含まれていますparse(s)


編集:

  • 関数の代わりに入力を受け取ります

2

Retina249 233バイト

(.)(?=.*¶\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

オンラインでお試しください!リンクにはテストケースが含まれます。説明:

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

_指定された変数が出現するたびにアフターを追加します。

L`.\w*

入力を項に分割します。

G`_

変数を参照した用語のみを保持します。

^\b
+

+最初の項に記号がない場合は、接頭辞aを付けます。

%O`._?\d*

各用語をアルファベット順に並べ替えます。(符号は一致しますが、それは問題ではありません。とにかく最初からソートされます。)

_\d+
*

変数のすべての指数を単項に変換します。

\b[a-z]
1$&

乗数なしで一時的に1をこれらの用語の前に付けます。

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

乗数を変数の指数で乗算し、結果を単項にします。

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

すべての用語を並べ替えます。

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

同じ記号の用語を追加します。

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

異なる符号の項を減算します。

G`\b_

別の記号の用語によってキャンセルされた用語を削除します。

\b_+
$.&

乗数を10進数に戻します。

_(__+)
$.1

3より大きい指数を減分し、10進数に戻します。

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

a)先行+符号を削除するb)すべての項を結合するc)変数の2乗をプレーン変数に変換するd)指数がない場合は変数を削除する

\b1([a-z])
$1

一時的に1を削除します。乗算するものがなくなった場合を除きます。

^$
0

項が残っていない場合、結果はゼロになります。

重複する用語をサポートすると、バイト数のほぼ半分のコストがかかります。用語を重複排除しなかった以前の123バイトのソリューション:

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

オンラインでお試しください!説明:

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

_指定された変数が出現するたびにアフターを追加します。

L`.\w*

入力を項に分割します。

G`_

変数を参照した用語のみを保持します。

_\d+
*

変数のすべての指数を単項に変換します。

\b[a-z]
1$&

乗数なしで一時的に1をこれらの用語の前に付けます。

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

乗数を変数の指数で乗算します。

_(__+)
$.1

3より大きい指数を減分し、10進数に戻します。

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

a)先行+符号を削除するb)すべての項を結合するc)変数の2乗をプレーン変数に変換するd)指数がない場合は変数を削除する

\b1([a-z])
$1

一時的に1を削除します。乗算するものがなくなった場合を除きます。

^$
0

項が残っていない場合、結果はゼロになります。


印象的ですが、TIOの例でこれら2つの用語をマージする必要があります。
Weijun Zhou

1
@WeijunZhou申し訳ありませんが、私はそのスペックの一部を見落としました。それについて考えさせて...
Neil

@WeijunZhouええと、バイト数が多すぎますが、うまく機能していると思います。
Neil

大変お疲れ様でした。これは、私がRetinaを学び始めるための良いポイントだと思います。
Weijun Zhou 2018


0

Physica、3バイト

これは新しい機能を使用しません。およびそのASCIIのみの代替は、10日以上前にDifferentiate導入されました。

デモ

式と変数の両方が文字列として渡されることを前提としています。テストコード:

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']]

正確な出力:

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

式の形式:*乗算、**指数、+および-それに応じた加算と減算。

Physica –ビジュアルデモ



弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.