Euler yöntemini uygulayın


9

Bu zorluğun amacı Euler yöntemini f (n) (x) = c biçimindeki diferansiyel denklemin çözümüne yaklaşmak için kullanmaktır .

Girişi, tam sayılar listesi olacak N inci değer f değerini temsil eder (n) (0). İlk tamsayı f (0), ikincisi f '(0), vb. Bu listedeki son tam sayı sabittir ve her zaman aynı kalır.

Ayrıca girdi , hedef değeri temsil eden pozitif (sıfır olmayan) bir tamsayı x olarak sağlanır (f (x) değerini tahmin etmeye çalışıyorsunuz). Euler yöntemi için adım boyutu her zaman 1 olacaktır. Bu nedenle, toplam x adım atmanız gerekecektir .

Eğer Euler yöntemiyle unfamliar değilseniz, burada girişi için bir açıklama detaylı bir örnektir [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

Esasen, oluşturulan tablodaki her bir hücre, üstündeki hücrenin ve üstteki ve sağdaki hücrenin toplamıdır. Böylece, f (a) = f (a-1) + f '(a-1); f '(a) = f' (a-1) + f '' (a-1); ve f '' (a) = f '' (a-1) + f '' '(a-1). Son cevap f (8) ≈ -8'dir. ††

Giriş listesi her zaman 2 veya daha fazla eleman içerecektir, bunların hepsi mutlak değerleri 10'dan düşük olacaktır. X ≥ 1 de garanti edilmektedir. Çıktı tek bir tamsayıdır, f (x) 'nin yaklaşımıdır. Giriş her iki sırayla da alınabilir ( x'ten önceki liste veya listeden önce x ). x ayrıca istenirse listenin ilk veya son öğesi olabilir.

Test senaryoları:

[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

†: bu durumda bir yaklaştırma yöntemi kullanmanın aslında aptal olduğu dikkat çekicidir. ancak, bu meydan okuma amacıyla mümkün olan en basit işlev seçilmiştir.

† → : gerçek değer -25⅓ olur, bu da bu yaklaşımı "çok iyi değil" olarak nitelendirir.



Yanıtlar:


3

Haskell , 38 bayt

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

Çevrimiçi deneyin!

39 bayttan geliştirildi:

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

Çıkışı yinelemeli olarak ifade eder l%n. Yukarı taşımak, azalmaya nve sağa hareket etmek, tail ltüm liste öğelerini bir boşluk sola kaydırmaya karşılık gelir . Yani, çıktı l%nyukarıdaki değer l%(n-1), artı yukarıdaki ve sağdaki değerdir(tail l)%(n-1)

Temel durum n==0ilk liste öğesini almaktır.

İdeal olarak, girdi bir polinom türevleri sonunda sıfıra dönüştüğü için sağa sonsuz sayıda sıfır ile doldurulur. Bunu 0aldığımızda bir ekleyerek bunu simüle ediyoruz tail.

Tuhaf alt 41:

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


3

Jöle , 6 5 bayt

Ḋ+$¡Ḣ

Çevrimiçi deneyin!

@Doorknob sayesinde -1 bayt

açıklama

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

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

Çevrimiçi deneyin!

Nasıl çalışır

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

Önceki 13 baytlık çözüm

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

Çevrimiçi deneyin!

Nasıl çalışır

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

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

Bu meydan okuma için matematik seviyorum.

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

Nasıl çalışır (sadece python 2 ile çalışır):

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

Çevrimiçi deneyin!

100 bayt alternatif paskal üçgen kullanımı ile

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

Nasıl çalışır (python 2 ve 3 için çalışır):

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

Bu formül x, paskal üçgen sırasının katsayılarını diziye eşleyerek çalışır . Paskal üçgeni öğelerinin her biri, satır ve dizinin seçim işleviyle belirlenir. Bu yeni dizinin toplamı, adresindeki çıktıya eşdeğerdir x. Newton yönteminin yinelenen süreci (örnekte gösterilen) tam olarak paskal üçgeninin inşası gibi davrandığından da sezgiseldir.

Çevrimiçi deneyin!

Döngüyü özyinelemeli bir işleve dönüştürerek 22 baytı azaltmak için ovs'a büyük teşekkürler


İşte geliştirilmiş bir sürüm. For döngüsünü özyinelemeli bir işleve dönüştürdüm
ovs

Ah, great idea @ovs
Graviton

daha da kısa yalnızca python2 çalışacağını Not
ovs

1

Haskell, 52 45 bayt

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

Kullanım örneği: [-3,3,-3,3,-3,3,-3,3,-3] # 15-> -9009. Çevrimiçi deneyin!

Nasıl çalışır

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

Düzenleme: @xnor 7 bayt kaydetti. Teşekkürler!


Ben yinelenen işlevi zipWith(+)=<<tail.(++[0]), yani listeyi daha sonra yerine önceden düzeltmek olduğunu düşünüyorum .
xnor

@xnor: evet, bu çok fazla bayt tasarrufu sağlar. Teşekkürler!
nimi

=<<
Zihnimi

@flawr: =<<işlev bağlamında kullanılan ve aşağıdaki gibi tanımlanır: (=<<) f g x = f (g x) x. Burada kullandığımız =<<: infix (f =<< g) xile f = zipWith(+)ve g = tailçevirir, zipWith(+) (tail x) x.
nimi

Ayrıntılı açıklama için teşekkür ederim, fonksiyon monad'ın farkında değildim!
Kusur

1

CJam , 12 bayt

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

Çevrimiçi deneyin!

açıklama

Kod, meydan okumada açıklanan prosedürü doğrudan uygular.

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

Aslında 7 bayt

;lr(♀█*

Çevrimiçi deneyin!

Nasıl çalışır

;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

Oktav , 42 bayt

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

Bu anonim bir işlevi tanımlar. Çevrimiçi deneyin!

açıklama

Çözelti, giriş dizisini ve sonuçtaki dizileri tekrar tekrar döndürerek hesaplanabilir [1, 1]. Ama iki kez evriştirerek veya üç kez ya ... ile [1, 1]karşılık gelir ile bir kez evriştirerek için [1, 2 ,1]ya [1, 3, 3, 1]... ya; yani Pascal üçgeninin bir sırası ile. Bu, Pascal düzen matrisinin anti-diyagonali olarak elde edilir x+1.


0

JavaScript (ES6), 41 bayt

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

@ Xnor'ın mükemmel Haskell cevabı. Önceki 47 baytlık çözüm.

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


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.