Implementieren Sie die Euler-Methode


9

Ziel dieser Herausforderung ist es, mit der Euler-Methode die Lösung einer Differentialgleichung der Form f (n) (x) = c zu approximieren .

Die Eingabe ist eine Liste von ganzen Zahlen, in denen der n- te Wert den Wert von f (n) (0) darstellt. Die erste ganze Zahl ist f (0), die zweite ist f '(0) und so weiter. Die letzte Ganzzahl in dieser Liste ist die Konstante und bleibt immer gleich.

Als Eingabe wird auch eine positive Ganzzahl x (ungleich Null) bereitgestellt , die den Zielwert darstellt (Sie versuchen, f (x) zu schätzen). Die Schrittgröße für die Euler-Methode ist immer 1. Daher müssen Sie insgesamt x Schritte ausführen.

Wenn Sie mit der Euler-Methode nicht vertraut sind, finden Sie hier ein detailliertes Beispiel mit einer Erklärung für die Eingabe [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

Im Wesentlichen ist jede Zelle in der generierten Tabelle die Summe der Zelle darüber und der Zelle darüber und rechts. Also ist f (a) = f (a-1) + f '(a-1); f '(a) = f' (a-1) + f '' (a-1); und f '' (a) = f '' (a-1) + f '' '(a-1). Die endgültige Antwort lautet f (8) ≈ -8. ††

Die Eingabeliste enthält immer 2 oder mehr Elemente, die alle absolute Werte unter 10 haben. X ≥ 1 ist ebenfalls garantiert. Die Ausgabe ist eine einzelne ganze Zahl, die Approximation von f (x). Die Eingabe kann in beliebiger Reihenfolge erfolgen (die Liste vor x oder x vor der Liste). Falls gewünscht, kann x auch das erste oder letzte Element der Liste sein.

Testfälle:

[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

†: Es ist bemerkenswert, dass die Verwendung einer Approximationsmethode in dieser Situation tatsächlich dumm ist. Für diese Herausforderung wurde jedoch die einfachstmögliche Funktion gewählt.

††: Der tatsächliche Wert ist zufällig -25⅓, was diese Annäherung als "nicht sehr gut" qualifizieren würde.



Antworten:


3

Haskell , 38 Bytes

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

Probieren Sie es online aus!

Verbessert von 39 Bytes:

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

Drückt die Ausgabe rekursiv aus l%n. Das Verschieben nach oben entspricht dem Dekrementieren n, und das Verschieben nach rechts entspricht tail ldem Verschieben aller Listenelemente um ein Leerzeichen nach links. Die Ausgabe l%nist also der Wert oben l%(n-1)plus der Wert oben und rechts(tail l)%(n-1)

Der Basisfall n==0ist das erste Listenelement.

Im Idealfall wird die Eingabe mit unendlich vielen Nullen rechts aufgefüllt, da die Ableitungen eines Polynoms schließlich Null werden. Wir simulieren dies, indem 0wir ein anhängen, wenn wir das nehmen tail.

Weird alt 41:

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


3

Gelee , 6 5 Bytes

Ḋ+$¡Ḣ

Probieren Sie es online aus!

-1 Byte dank @Doorknob

Erläuterung

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

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

Probieren Sie es online aus!

Wie es funktioniert

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

Vorherige 13-Byte-Lösung

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

Probieren Sie es online aus!

Wie es funktioniert

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

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

Ich liebe die Mathematik für diese Herausforderung.

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

Wie es funktioniert (funktioniert nur mit 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

Probieren Sie es online aus!

100 Byte wechseln sich mit der Verwendung eines Pascal-Dreiecks ab

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

Wie es funktioniert (funktioniert für Python 2 und 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

Diese Formel funktioniert durch Abbildung der Koeffizienten xder Pascal-Dreiecksreihe auf das Array. Jedes Element des Pascal-Dreiecks wird durch die Auswahlfunktion der Zeile und des Index bestimmt. Die Summe dieses neuen Arrays entspricht der Ausgabe beix . Es ist auch intuitiv, da der iterierte Prozess der Newton-Methode (im Beispiel gezeigt) genau wie die Konstruktion des Pascal-Dreiecks wirkt.

Probieren Sie es online aus!

Ein großes Dankeschön an ovs für die Reduzierung von 22 Bytes durch Umwandlung der Schleife in eine rekursive Funktion


Hier ist eine verbesserte Version. Ich konvertierte die for-Schleife in eine rekursive Funktion
ovs

Ah, tolle Idee @ovs
Graviton

noch kürzer Beachten Sie, dass es nur mit Python2 funktioniert
ovs

1

Haskell, 52 45 Bytes

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

Anwendungsbeispiel: [-3,3,-3,3,-3,3,-3,3,-3] # 15-> -9009. Probieren Sie es online aus!

Wie es funktioniert

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

Bearbeiten: @xnor hat 7 Bytes gespeichert. Vielen Dank!


Ich denke, die iterierte Funktion kann sein zipWith(+)=<<tail.(++[0]), dh die Liste vorher und nicht danach reparieren.
xnor

@xnor: Ja, das spart viele Bytes. Vielen Dank!
Nimi

Ich kann mich einfach nicht um die Verwendung von =<<hier
kümmern

@flawr: =<<wird im Funktionskontext verwendet und ist definiert als : (=<<) f g x = f (g x) x. Hier verwenden wir das =<<Infix: (f =<< g) xmit f = zipWith(+)und g = tail, was übersetzt bedeutet zipWith(+) (tail x) x.
Nimi

Vielen Dank für die ausführliche Erklärung, mir war die Funktionsmonade nicht bekannt!
Fehler

1

CJam , 12 Bytes

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

Probieren Sie es online aus!

Erläuterung

Der Code implementiert direkt die in der Herausforderung beschriebene Prozedur.

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

Eigentlich 7 Bytes

;lr(♀█*

Probieren Sie es online aus!

Wie es funktioniert

;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

Oktave , 42 Bytes

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

Dies definiert eine anonyme Funktion. Probieren Sie es online aus!

Erläuterung

Die Lösung könnte berechnet werden, indem das Eingabearray und die resultierenden Arrays wiederholt mit gefaltet werden [1, 1]. Aber zweimal oder dreimal [1, 1]zu falten oder ... mit entspricht einer einmaligen Faltung mit [1, 2 ,1]oder [1, 3, 3, 1]oder oder; das heißt, mit einer Reihe des Pascal-Dreiecks. Dies wird als Antidiagonale der Pascal-Ordnungsmatrix erhalten x+1.


0

JavaScript (ES6), 41 Byte

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

Port of @ xnors ausgezeichnete Haskell-Antwort. Vorherige 47-Byte-Lösung.

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


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.