Implementa il metodo di Eulero


9

L'obiettivo di questa sfida è utilizzare il metodo di Eulero per approssimare la soluzione di un'equazione differenziale della forma f (n) (x) = c.

L'ingresso sarà una lista di interi in cui il n esimo valore rappresenta il valore di f (n) (0). Il primo numero intero è f (0), il secondo è f '(0) e così via. L'ultimo numero intero in questo elenco è la costante e rimarrà sempre lo stesso.

Come input verrà fornito anche un numero intero positivo (diverso da zero) x , che rappresenta il valore target (si sta tentando di stimare f (x)). La dimensione del passo per il metodo di Eulero sarà sempre 1. Quindi, dovrai fare un totale di x passi.

Se non hai familiarità con il metodo di Eulero, ecco un esempio dettagliato con una spiegazione per l'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

In sostanza, ogni cella nella tabella generata è la somma della cella sopra di essa e la cella sopra e a destra. Quindi, f (a) = f (a-1) + f '(a-1); f '(a) = f' (a-1) + f '' (a-1); e f '' (a) = f '' (a-1) + f '' '(a-1). La risposta finale è f (8) ≈ -8. ††

L'elenco di input conterrà sempre 2 o più elementi, tutti con valori assoluti inferiori a 10. x ≥ 1 è inoltre garantito. L'output è un singolo intero, l'approssimazione di f (x). L'input può essere preso in entrambi gli ordini (l'elenco prima di x o x prima dell'elenco). x può anche essere il primo o l'ultimo elemento dell'elenco, se lo si desidera.

Casi 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

†: è da notare che l'utilizzo di un metodo di approssimazione in questa situazione è, in effetti, stupido. tuttavia, ai fini di questa sfida è stata scelta la funzione più semplice possibile.

††: il valore effettivo risulta essere -25⅓, il che qualificherebbe questa approssimazione come "non molto buona".



Risposte:


3

Haskell , 38 byte

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

Provalo online!

Migliorato da 39 byte:

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

Esprime in modo ricorsivo l'output l%n. Lo spostamento verso l'alto corrisponde al decremento ne lo spostamento verso destra corrisponde a prendere tail lper spostare tutti gli elementi dell'elenco di uno spazio a sinistra. Quindi, l'output l%nè il valore sopra l%(n-1), più il valore sopra e verso destra(tail l)%(n-1)

Il caso base n==0è quello di prendere il primo elemento della lista.

Idealmente, l'input verrebbe riempito con infiniti molti zeri a destra, poiché le derivate di un polinomio alla fine diventerebbero zero. Simuliamo questo aggiungendo un 0quando prendiamo il tail.

Strano alt 41:

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


3

Gelatina , 6 5 byte

Ḋ+$¡Ḣ

Provalo online!

-1 byte grazie a @Doorknob

Spiegazione

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

Provalo online!

Come funziona

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

Precedente soluzione a 13 byte

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

Provalo online!

Come funziona

{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

Adoro la matematica per questa sfida.

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

Come funziona (funziona solo con 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

Provalo online!

100 byte si alternano con l'uso del triangolo pascal

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

Come funziona (funziona per Python 2 e 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

Questa formula funziona mappando i coefficienti della riga xdel triangolo di Pascal sull'array. Ogni elemento del triangolo pasquale è determinato dalla funzione di scelta della riga e dell'indice. La somma di questo nuovo array è equivalente all'output di x. È anche intuitivo poiché il processo iterato del metodo newton (mostrato nell'esempio) agisce esattamente come la costruzione del triangolo di Pascal.

Provalo online!

Un grande grazie a ovs per la riduzione di 22 byte convertendo il loop in una funzione ricorsiva


Ecco una versione migliorata. Ho convertito il ciclo for in una funzione ricorsiva
ovs

Ah, ottima idea @ovs
Graviton,

ancora più breve Nota che funzionerà solo con python2
ovs

1

Haskell, 52 45 byte

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

Esempio di utilizzo: [-3,3,-3,3,-3,3,-3,3,-3] # 15-> -9009.Provalo online!

Come funziona

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

Modifica: @xnor ha salvato 7 byte. Grazie!


Penso che la funzione ripetuta possa essere zipWith(+)=<<tail.(++[0]), ovvero correggere l'elenco in anticipo anziché in seguito.
xnor

@xnor: sì, questo consente di risparmiare molti byte. Grazie!
nimi,

Non riesco proprio a pensare a questo uso =<<, è pazzesco :)
Flawr

@flawr: =<<è utilizzato nel contesto funzione ed è definito come: (=<<) f g x = f (g x) x. Qui usiamo =<<infix: (f =<< g) xcon f = zipWith(+)e g = tail, che si traduce in zipWith(+) (tail x) x.
nimi,

Grazie per la spiegazione dettagliata, non ero a conoscenza della funzione monade!
flawr

1

CJam , 12 byte

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

Provalo online!

Spiegazione

Il codice implementa direttamente la procedura descritta nella sfida.

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

In realtà , 7 byte

;lr(♀█*

Provalo online!

Come funziona

;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

Ottava , 42 byte

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

Questo definisce una funzione anonima. Provalo online!

Spiegazione

La soluzione può essere calcolata contorcendo ripetutamente l'array di input e gli array risultanti con [1, 1]. Ma contorto due volte, o tre volte, o ... con [1, 1]corrisponde a contorto una volta con [1, 2 ,1], o [1, 3, 3, 1], o ...; cioè con una fila del triangolo pasquale. Questo si ottiene come anti-diagonale della matrice dell'ordine di Pascal x+1.


0

JavaScript (ES6), 41 byte

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

Ottima risposta Haskell di Port of @ xnor. Precedente soluzione a 47 byte.

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

0

Python 3 con Numpy , 82 byte

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

Simile alla mia risposta MATL , ma usando una convoluzione a grandezza naturale, e quindi il risultato è la x-esima voce dell'array finale.

Provalo online!


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.