Terapkan metode Euler


9

Tujuan dari tantangan ini adalah menggunakan metode Euler untuk memperkirakan solusi dari persamaan diferensial dari bentuk f (n) (x) = c.

Input akan menjadi daftar bilangan bulat di mana nilai n mewakili nilai f (n) (0). Bilangan bulat pertama adalah f (0), yang kedua adalah f '(0), dan seterusnya. Bilangan bulat terakhir dalam daftar ini adalah konstan dan akan selalu tetap sama.

Juga disediakan sebagai masukan akan menjadi positif (nol) bilangan bulat x , yang mewakili nilai target (Anda mencoba untuk memperkirakan f (x)). Ukuran langkah untuk metode Euler akan selalu 1. Dengan demikian, Anda harus mengambil x langkah total.

Jika Anda tidak terbiasa dengan metode Euler, berikut adalah contoh terperinci dengan penjelasan untuk input [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

Pada dasarnya, setiap sel dalam tabel yang dihasilkan adalah jumlah sel di atasnya dan sel di atas dan ke kanan. Jadi, f (a) = f (a-1) + f '(a-1); f '(a) = f' (a-1) + f '' (a-1); dan f '' (a) = f '' (a-1) + f '' '(a-1). Jawaban akhir adalah f (8) ≈ -8. ††

Daftar input akan selalu mengandung 2 atau lebih elemen, yang semuanya akan memiliki nilai absolut kurang dari 10. x ≥ 1 juga dijamin. Outputnya adalah integer tunggal, perkiraan f (x). Input dapat diambil dalam urutan apa pun (daftar sebelum x , atau x sebelum daftar). x juga bisa menjadi elemen pertama atau terakhir dari daftar, jika diinginkan.

Kasus uji:

[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

†: Perlu dicatat bahwa menggunakan metode pendekatan dalam situasi ini, sebenarnya, bodoh. Namun, fungsi yang paling sederhana mungkin dipilih untuk keperluan tantangan ini.

††: nilai aktualnya adalah -25⅓, yang akan memenuhi syarat perkiraan ini sebagai "tidak terlalu baik."



Jawaban:


3

Haskell , 38 byte

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

Cobalah online!

Ditingkatkan dari 39 byte:

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

Secara ekspresif mengekspresikan output l%n. Pindah ke atas terkait dengan pengurangan n, dan bergerak ke kanan berhubungan dengan tail luntuk menggeser semua elemen daftar satu ruang tersisa. Jadi, outputnya l%nadalah nilai di atas l%(n-1), ditambah nilai di atas dan di sebelah kanan(tail l)%(n-1)

Kasing dasar n==0adalah untuk mengambil elemen daftar pertama.

Idealnya, input akan diisi dengan banyak nol di sebelah kanan, karena turunan dari polinomial akhirnya menjadi nol. Kami mensimulasikan ini dengan menambahkan 0ketika kami mengambil tail.

Aneh alt 41:

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


3

Jelly , 6 5 byte

Ḋ+$¡Ḣ

Cobalah online!

-1 byte terima kasih kepada @Doorknob

Penjelasan

Ḋ+$¡Ḣ  - 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

Brachylog , 13 12 byte

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

Cobalah online!

Bagaimana itu bekerja

{,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]

Solusi 13 byte sebelumnya

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

Cobalah online!

Bagaimana itu bekerja

{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 byte

#&@@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

Python , 80 58 byte

Cintai matematika untuk tantangan ini.

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

Cara kerjanya (hanya bekerja dengan 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

Cobalah online!

Alternatif 100 byte dengan menggunakan segitiga pascals

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

Cara kerjanya (berfungsi untuk python 2 dan 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

Formula ini bekerja dengan memetakan koefisien baris xdari pascal segitiga ke array. Setiap elemen segitiga pascal ditentukan oleh fungsi pilih dari baris dan indeks. Jumlah array baru ini sama dengan output di x. Ini juga intuitif karena proses iterasi metode newton (ditunjukkan dalam contoh) bertindak persis seperti konstruksi segitiga pascals.

Cobalah online!

Terima kasih banyak untuk ovs karena mengurangi 22 byte dengan mengubah loop menjadi fungsi rekursif


Ini adalah versi yang ditingkatkan. Saya mengkonversi loop untuk fungsi rekursif
ovs

Ah, ide bagus @ovs
Graviton

lebih pendek. Perhatikan bahwa ini hanya akan bekerja dengan python2
ovs

1

Haskell, 52 45 byte

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

Contoh penggunaan: [-3,3,-3,3,-3,3,-3,3,-3] # 15-> -9009. Cobalah online!

Bagaimana itu bekerja

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

Edit: @xnatau disimpan 7 byte. Terima kasih!


Saya pikir fungsi yang diulang bisa zipWith(+)=<<tail.(++[0]), yaitu memperbaiki daftar sebelumnya daripada sesudahnya.
xnor

@ xnor: ya, itu menghemat banyak byte. Terima kasih!
nimi

Saya hanya tidak bisa membungkus pikiran saya dengan penggunaan di =<<sini, ini gila :)
flawr

@flawr: =<<digunakan dalam konteks fungsi dan didefinisikan sebagai: (=<<) f g x = f (g x) x. Di sini kita menggunakan =<<infix: (f =<< g) xwith f = zipWith(+)dan g = tail, yang diterjemahkan menjadi zipWith(+) (tail x) x.
nimi

Terima kasih atas penjelasan detailnya, saya tidak mengetahui fungsi monad!
flawr

1

CJam , 12 byte

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

Cobalah online!

Penjelasan

Kode secara langsung mengimplementasikan prosedur yang dijelaskan dalam tantangan.

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

Sebenarnya , 7 byte

;lr(♀█*

Cobalah online!

Bagaimana itu bekerja

;lr(♀█*  input:
         8, [4, -5, 3, -1]
         top of stack at the right
;        duplicate
         8, [4, -5, 3, -1], [4, -5, 3, -1]
 l       length
         8, [4, -5, 3, -1], 4
  r      range
         8, [4, -5, 3, -1], [0, 1, 2, 3]
   (     rotate stack
         [4, -5, 3, -1], [0, 1, 2, 3], 8
    ♀█   map "n choose r"
         [4, -5, 3, -1], [1, 8, 28, 56]
      *  dot product
         -8

1

Oktaf , 42 byte

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

Ini mendefinisikan fungsi anonim. Cobalah online!

Penjelasan

Solusi dapat dihitung dengan berulang kali menggabungkan array input dan array yang dihasilkan dengan [1, 1]. Tetapi berbelit dua kali, atau tiga kali, atau ... dengan [1, 1]berkorespondensi dengan berbelit-belit sekali dengan [1, 2 ,1], atau [1, 3, 3, 1], atau ...; yaitu, dengan deretan segitiga Pascal. Ini diperoleh sebagai anti-diagonal dari matriks orde Pascal x+1.


0

JavaScript (ES6), 41 byte

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

Port @ xnor jawaban Haskell yang luar biasa. Solusi 47 byte sebelumnya.

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


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.