オイラー法を実装する


9

この課題の目標は、オイラー法を使用して、形式f (n)(x)= cの微分方程式の解を近似することです。

入力は、n番目の値がf (n)(0)の値を表す整数のリストになります。最初の整数はf(0)、2番目の整数はf '(0)のようになります。このリストの最後の整数は定数であり、常に同じままです。

また、ターゲット値を表す正の(ゼロ以外の)整数xも入力として提供されます(f(x)を推定しようとしています)。オイラー法のステップサイズは常に1になります。したがって、合計xステップを取る必要があります。

あなたはオイラー法とunfamliarている場合は、ここでの入力のための説明と詳細な例である[4, -5, 3, -1]X = 8。

x       f(x)      f'(x)     f''(x)    f'''(x)
0          4         -5          3         -1
1   4-5 = -1  -5+3 = -2   3-1 =  2         -1
2  -1-2 = -3  -2+2 =  0   2-1 =  1         -1
3  -3+0 = -3   0+1 =  1   1-1 =  0         -1
4  -3+1 = -2   1+0 =  1   0-1 = -1         -1
5  -2+1 = -1   1-1 =  0  -1-1 = -2         -1
6  -1+0 = -1   0-2 = -2  -2-1 = -3         -1
7  -1-2 = -3  -2-3 = -5  -3-1 = -4         -1
8  -3-5 = -8

基本的に、生成されたテーブル内の各セルは、その上のセルと上のセルと右のセルの合計です。したがって、f(a)= f(a-1)+ f '(a-1); f '(a)= f'(a-1)+ f ''(a-1); およびf ''(a)= f ''(a-1)+ f '' '(a-1)。最終的な答えはf(8)≈-8です。††

入力リストは常に全てが10未満の絶対値を有する、2種以上の元素を含有するX 1も保証される≥。出力は、f(x)の近似値である単一の整数です。入力は、どちらの順序(前のリストに入れてもよいX、又はXリストの前に)。xは、必要に応じて、リストの最初または最後の要素にすることもできます。

テストケース:

[4, -5, 3, -1], x = 8 => -8
[1, 2, 3, 4, 5, 6], x = 10 => 3198
[1, 3, 3, 7], x = 20 => 8611
[-3, 3, -3, 3, -3, 3, -3, 3, -3], x = 15 => -9009
[1, 1], x = 1 => 2

†:この状況で近似法を使用することは、実際には愚かであることは注目に値します。ただし、この課題のために、可能な限り単純な関数が選択されました。

††:実際の値はたまたま-25⅓であり、この近似は「あまり良くない」と見なされます。



回答:


3

Haskell、38バイト

l%n|n<1=l!!0|m<-n-1=l%m+tail(l++[0])%m

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

39バイトから改善:

l%0=l!!0
l%n=l%(n-1)+tail(l++[0])%(n-1)

出力を再帰的に表現しますl%n。上に移動することは、デクリメントnに対応し、右に移動することはtail l、すべてのリスト要素を1スペース左にシフトすることを意味します。したがって、出力l%nは上記l%(n-1)の値に上と右の値を加えたものになります(tail l)%(n-1)

基本的なケースn==0は、最初のリスト要素を取ることです。

理想的には、多項式の導関数が最終的にゼロになるため、入力は無限に多くのゼロで右側に埋め込まれます。これをシミュレートするには0、を取得するときにa を追加しtailます。

奇妙な代替41:

(iterate(\q l->q l+q(tail l++[0]))head!!)


3

ゼリー6 5バイト

Ḋ+$¡Ḣ

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

@Doorknobのおかげで-1バイト

説明

Ḋ+$¡Ḣ  - Main dyadic link. First input list, second x
       - (implicit) on the previous iteration (starting at input list)
Ḋ      - Dequeue. e.g. [-5,3,-1]
 +     - Add this to
       - (implicit) the previous iteration. e.g. [4+(-5),-5+3,3+(-1),-1+0]
  $¡   - apply this successively x times
    Ḣ  - get the first element from the resultant list

3

Brachylog13 12バイト

{,0s₂ᶠ+ᵐ}ⁱ⁾h

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

使い方

{,0s₂ᶠ+ᵐ}ⁱ⁾h
{       }ⁱ⁾   iterate the previous predicate
              to the array specified by first element of input
              as many times as the second element of input
           h  and get the first element

              example input to predicate: [4, _5, 3, _1]
 ,0           append 0: [4, _5, 3, _1, 0]
   s₂ᶠ        find all substrings with length 2:
              [[4, _5], [_5, 3], [3, _1], [_1, 0]]
      +ᵐ      "add all the elements" mapped to each subarray:
              [_1, _2, _2, _1]

以前の13バイトのソリューション

{b,0;?z+ᵐ}ⁱ⁾h

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

使い方

{b,0;?z+ᵐ}ⁱ⁾h
{        }ⁱ⁾   iterate the previous predicate
               to the array specified by first element of input
               as many times as the second element of input
            h  and get the first element

               example input to predicate: [4, _5, 3, _1]
 b             remove the first element: [_5, 3, _1]
  ,0           append 0: [_5, 3, _1, 0]
    ;?         pair with input: [[_5, 3, _1, 0], [4, _5, 3, _1]]
      z        zip: [[_5, 4], [3, _5], [_1, 3], [0, _1]]
       +ᵐ      "add all the elements" mapped to each subarray:
               [_1, _2, _2, _1]

2

Mathematica、32バイト

#&@@Nest[#+Rest@#~Append~0&,##]&
                               &  make a pure function
    Nest[                 &,##]   call inner function as many times as specified
           Rest@#                 drop the first element of the list
                 ~Append~0        and add a 0 to get [b,c,d,0]
         #+                       add original list to get [a+b,b+c,c+d,d]
#&@@                              take the first element after x iterations

2

Python80 58バイト

この挑戦の数学が大好きです。

f=lambda a,x:x and f(map(sum,zip(a,a[1:]+[0])),x-1)or a[0]

仕組み(python 2でのみ機能):

f=lambda a,x:                                              - new lambda function
             x and                                         - iterate itself x times
                     map(sum,zip(a,a[1:]+[0]))             - e.g; f(a) = f(a-1) + f'(a-1)
                   f(                         ,x-1)        - iterate new array into itself
                                                   or a[0] - return first element

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

パスカルの三角形を使用した100バイトの代替

from math import factorial as F
f=lambda a,x:sum([(a+[0]*x)[i]*F(x)/(F(x-i)*F(i))for i in range(x)])

仕組み(python 2および3で動作):

sum([                                                ]) - take the sum of array
     (a+[0]*x)                                        - append x zeros
              [i]*F(x)/(F(x-i)*F(i))                  - multiply each element by x choose i
                                    for i in range(x) - do this for every element

この式xは、パスカル三角形の行の係数を配列にマッピングすることで機能します。パスカル三角形の各要素は、行とインデックスの選択機能によって決定されます。この新しい配列の合計は、での出力と同じxです。ニュートン法の反復プロセス(例に示されている)がパスカル三角形の構築とまったく同じように機能するため、直感的でもあります。

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

ループを再帰関数に変換して22バイトを削減してくれたovsに感謝


これは改良版です。forループを再帰関数に変換しました
ovs

ああ、素晴らしいアイデア@ovs
Graviton

さらに短いのは 、python2でのみ機能することに注意してください
ovs

1

Haskell、52 45バイト

l#n=iterate(zipWith(+)=<<tail.(++[0]))l!!n!!0

使用例:[-3,3,-3,3,-3,3,-3,3,-3] # 15-> -9009オンラインでお試しください!

使い方

iterate(      )l          -- apply the function again and again starting with l
                          -- and collect the intermediate results in a list
                          -- the function is
          (++[0])         -- append a zero 
  zipWith(+)=<<tail       -- and build list of neighbor sums
                     !!0  -- take the first element from
                  !!n     -- the nth result

編集:@xnorは7バイトを節約しました。ありがとう!


反復関数はzipWith(+)=<<tail.(++[0])、つまりリストを後で修正するのではなく事前に修正できると思います。
xnor 2017年

@xnor:はい、多くのバイトを節約します。ありがとう!
nimi

私は=<<ここの使用を心に留めることはできません、これは
異常

@flawr:=<<は関数コンテキストで使用され、次のように定義されます(=<<) f g x = f (g x) x。ここでは、=<<infix:(f =<< g) xwith f = zipWith(+)およびを使用g = tailzipWith(+) (tail x) xます。これはに変換されます。
nimi

詳細な説明ありがとうございます、私はfunctionモナドを知りませんでした!
flawr

1

CJam、12バイト

q~{_(;.+}*0=

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

説明

コードは、チャレンジで説明されている手順を直接実装します。

q~            e# Read input and evaluate. Pushes the array and the number x
  {     }*    e# Do the following x times
   _          e# Duplicate array
    (;        e# Remove first element
      .+      e# Vectorized sum. The last element in the first array, which doesn't 
              e# have a corresponding entry in the second, will be left as is
          0=  e# Get first element. Implicitly display




1

オクターブ、42バイト

@(a,x)conv(a,diag(flip(pascal(x+1))))(x+1)

これは無名関数を定義します。 オンラインでお試しください!

説明

解は、入力配列と結果の配列を繰り返し畳み込むことによって計算できます[1, 1]。ただし、2回、3回、または...での[1, 1]たたみ込みは[1, 2 ,1]、1つ[1, 3, 3, 1]、または、または...での1回のたたみ込みに対応します。つまり、Pascalトライアングルの行があります。これは、次数のパスカル行列の逆対角として取得されx+1ます。


0

JavaScript(ES6)、41バイト

f=(a,x,[b,...c]=a)=>x--?f(a,x)+f(c,x):b|0

@xnorの優れたHaskell回答のポート。以前の47バイトのソリューション。

f=(a,x)=>x--?f(a.map((e,i)=>e+~~a[i+1]),x):a[0]


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