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.