Implémenter la méthode d'Euler

9

Le but de ce défi est d'utiliser la méthode d' Euler pour approximer la solution d'une équation différentielle de la forme f (n) (x) = c.

L'entrée sera une liste d'entiers dans laquelle la n ème valeur représente la valeur de f (n) (0). Le premier entier est f (0), le second est f '(0), et ainsi de suite. Le dernier entier de cette liste est la constante et restera toujours le même.

Un nombre entier positif (non nul) x , qui représente la valeur cible (vous essayez d'estimer f (x)), est également fourni en entrée . La taille du pas pour la méthode d'Euler sera toujours 1. Ainsi, vous devrez effectuer x pas au total.

Si vous n'êtes pas familier avec la méthode d'Euler, voici un exemple détaillé avec une explication pour l'entrée [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

Essentiellement, chaque cellule du tableau généré est la somme de la cellule au-dessus et de la cellule au-dessus et à droite. Donc, f (a) = f (a-1) + f '(a-1); f '(a) = f' (a-1) + f '' (a-1); et f '' (a) = f '' (a-1) + f '' '(a-1). La réponse finale est f (8) ≈ -8. ††

La liste d'entrée contiendra toujours 2 éléments ou plus, qui auront tous des valeurs absolues inférieures à 10. x ≥ 1 est également garanti. La sortie est un entier unique, l'approximation de f (x). L'entrée peut être prise dans l'un ou l'autre ordre (la liste avant x ou x avant la liste). x peut également être le premier ou le dernier élément de la liste, si vous le souhaitez.

Cas de test:

[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

†: il est à noter que l'utilisation d'une méthode d'approximation dans cette situation est, en fait, stupide. cependant, la fonction la plus simple possible a été choisie aux fins de ce défi.

††: la valeur réelle se situe à -25⅓, ce qui qualifierait cette approximation de "pas très bonne".

Poignée de porte
la source

Réponses:

3

Haskell , 38 octets

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

Essayez-le en ligne!

Amélioré de 39 octets:

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

Exprime récursivement la sortie l%n. Monter correspond à décrémenter n, et déplacer à droite correspond à prendre tail lpour décaler tous les éléments de la liste d'un espace vers la gauche. Ainsi, la sortie l%nest la valeur ci l%(n-1)- dessus , plus la valeur au-dessus et à droite(tail l)%(n-1)

Le cas de base n==0est de prendre le premier élément de la liste.

Idéalement, l'entrée serait complétée par une infinité de zéros vers la droite, car les dérivées d'un polynôme finissent par devenir nulles. Nous simulons cela en ajoutant un 0lorsque nous prenons le tail.

Bizarre alt 41:

(iterate(\q l->q l+q(tail l++[0]))head!!)
xnor
la source
3

MATL , 9 octets

:"TTZ+]1)

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

:"      % Implicitly input x. Do the following x times
  TT    %   Push [1 1]
  Z+    %   Convolution, keeping size. Implicitly inputs array the first time
]       % End
1)      % Get first entry. Implictly display
Luis Mendo
la source
3

Gelée , 6 5 octets

Ḋ+$¡Ḣ

Essayez-le en ligne!

-1 octet grâce à @Doorknob

Explication

Ḋ+$¡Ḣ  - 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
fireflame241
la source
3

Brachylog , 13 12 octets

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

Essayez-le en ligne!

Comment ça fonctionne

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

Solution précédente de 13 octets

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

Essayez-le en ligne!

Comment ça fonctionne

{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]
Leaky Nun
la source
2

Mathematica, 32 octets

#&@@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
Poignée de porte
la source
2

Python , 80 58 octets

J'adore les mathématiques pour ce défi.

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

Comment ça marche (ne fonctionne qu'avec 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

Essayez-le en ligne!

100 octets alternés avec utilisation du triangle 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)])

Comment ça marche (fonctionne pour python 2 et 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

Cette formule fonctionne en mappant les coefficients de la rangée xde triangle pascals sur le tableau. Chaque élément du triangle pascal est déterminé par la fonction de choix de la ligne et de l'index. La somme de ce nouveau tableau est équivalente à la sortie de x. Il est également intuitif car le processus itéré de la méthode newtons (illustré dans l'exemple) agit exactement comme la construction d'un triangle pascal.

Essayez-le en ligne!

Un grand merci aux ovs pour avoir réduit 22 octets en convertissant la boucle en une fonction récursive

Graviton
la source
Voici une version améliorée. J'ai converti la boucle for en une fonction récursive
ovs
Ah, super idée @ovs
Graviton
encore plus court Notez qu'il ne fonctionnera qu'avec python2
ovs
1

Haskell, 52 45 octets

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

Exemple d'utilisation: [-3,3,-3,3,-3,3,-3,3,-3] # 15-> -9009. Essayez-le en ligne!

Comment ça fonctionne

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

Modifier: @xnor a enregistré 7 octets. Merci!

nimi
la source
Je pense que la fonction itérée peut être zipWith(+)=<<tail.(++[0]), c'est-à-dire fixer la liste avant plutôt qu'après.
xnor
@xnor: oui, cela économise beaucoup d'octets. Merci!
nimi
Je ne peux tout simplement pas penser à l'utilisation d' =<<ici, c'est fou :)
flawr
@flawr: =<<est utilisé dans le contexte de la fonction et est définie comme suit: (=<<) f g x = f (g x) x. Ici, nous utilisons =<<infix: (f =<< g) xavec f = zipWith(+)et g = tail, ce qui se traduit par zipWith(+) (tail x) x.
nimi
Merci pour l'explication détaillée, je n'étais pas au courant de la fonction monade!
flawr
1

CJam , 12 octets

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

Essayez-le en ligne!

Explication

Le code implémente directement la procédure décrite dans le challenge.

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
Luis Mendo
la source
1

Pyth , 10 octets

s.e*b.cQkE

Suite de tests.

Comment ça fonctionne

s.e*b.cQkE
 .e      E   for (b,k) in enumerated(array):
     .cQk        (input) choose (k)
   *b            * b
s            sum
Leaky Nun
la source
1

APL (Dyalog) , 29 octets

{0=⍺:⊃⍵
(⍺-1)∇(+/¨2,/⍵),¯1↑⍵}

Essayez-le en ligne!

Il s'agit d'un dfn récursif, mais il s'avère trop verbeux. Golf en cours ...

user41805
la source
1

En fait , 7 octets

;lr(♀█*

Essayez-le en ligne!

Comment ça fonctionne

;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
Leaky Nun
la source
1

Octave , 42 octets

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

Cela définit une fonction anonyme. Essayez-le en ligne!

Explication

La solution pourrait être calculée en convoluant à plusieurs reprises le tableau d'entrée et les tableaux résultants avec [1, 1]. Mais convoluer deux fois, ou trois fois, ou ... avec [1, 1]correspond à convoluer une fois avec [1, 2 ,1], ou [1, 3, 3, 1], ou ...; c'est-à-dire avec une rangée du triangle Pascal. Ceci est obtenu comme l'anti-diagonale de la matrice d'ordre Pascal x+1.

Luis Mendo
la source
0

JavaScript (ES6), 41 octets

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

Port de @ xnor excellente réponse Haskell. Solution précédente de 47 octets.

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

Python 3 avec Numpy , 82 octets

import numpy
def f(a,x):
 for n in range(x):a=numpy.convolve(a,[1,1])
 return a[x]

Semblable à ma réponse MATL , mais en utilisant une convolution pleine taille, et donc le résultat est la x-ème entrée du tableau final.

Essayez-le en ligne!

Luis Mendo
la source