Впровадити метод Ейлера


9

Мета цієї задачі - використовувати метод Ейлера для наближення розв’язку диференціального рівняння виду f (n) (x) = c.

Вхідним буде перелік цілих чисел, у яких n- е значення представляє значення f (n) (0). Перше ціле число - f (0), друге - f '(0) тощо. Останнє ціле число у цьому списку є постійним і завжди залишатиметься таким же.

Також в якості введення буде представлено додатне (ненульове) ціле число x , яке представляє цільове значення (ви намагаєтеся оцінити f (x)). Розмір кроків для методу Ейлера завжди буде 1. Таким чином, вам потрібно буде зробити x кроків усього.

Якщо ви не знайомі з методом Ейлера, ось детальний приклад з поясненням для введення [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

По суті, кожна клітинка в генерованій таблиці - це сума комірки над нею та комірки вгорі та праворуч. Отже, f (a) = f (a-1) + f '(a-1); f '(a) = f' (a-1) + f '' (a-1); і f '' (a) = f '' (a-1) + f '' '(a-1). Остаточна відповідь - f (8) ≈ -8. †Kl

Список вводу завжди буде містити 2 або більше елементів, всі з яких матимуть абсолютні значення менше 10. x ≥ 1 також гарантується. Вихід - це єдине ціле число, наближення f (x). Введення може бути прийнято в будь-якому порядку (список перед x , або x перед списком). x, також, може бути першим чи останнім елементом списку.

Тестові приклади:

[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

†: помітно, що використання методу наближення в цій ситуації насправді нерозумно. проте для цілей цього виклику було обрано найпростішу можливу функцію.

†Kan: фактичне значення буває -25⅓, що може визначити це наближення як "не дуже добре".



Відповіді:


3

Хаскелл , 38 байт

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

Спробуйте в Інтернеті!

Покращено з 39 байтів:

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

Рекурсивно виражає результат l%n. Переміщення вгору відповідає декрементації n, а переміщення вправо відповідає tail lпереміщенню всіх елементів списку на один пробіл вліво. Отже, вихід l%n- це значення вище l%(n-1), плюс значення вище та праворуч(tail l)%(n-1)

Основний випадок n==0- це взяти перший елемент списку.

В ідеалі, вхід був би прокладений нескінченно багатьма нулями праворуч, оскільки похідні многочлена з часом стають нульовими. Ми моделюємо це, додаючи, 0коли беремо tail.

Дивний альт 41:

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


3

Желе , 6 5 байт

Ḋ+$¡Ḣ

Спробуйте в Інтернеті!

-1 байт завдяки @Doorknob

Пояснення

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

Брахілог , 13 12 байт

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

Спробуйте в Інтернеті!

Як це працює

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

Попереднє 13-байтове рішення

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

Спробуйте в Інтернеті!

Як це працює

{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

Математика, 32 байти

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

Пітон , 80 58 байт

Любіть математику для цього виклику.

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

Як це працює (працює лише з 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

Спробуйте в Інтернеті!

100 байт чергуються з використанням трикутника 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)])

Як це працює (працює для python 2 і 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

Ця формула працює шляхом зіставлення коефіцієнтів рядки xз Трикутник Паскаля на масив. Кожен елемент трикутника паскалів визначається функцією вибору рядка та індексу. Сума цього нового масиву еквівалентна виводу при x. Він також інтуїтивно зрозумілий, оскільки ітераційний процес методу Ньютона (показаний у прикладі) діє саме як побудова трикутника паскалів.

Спробуйте в Інтернеті!

Велика подяка ovs за скорочення 22 байт шляхом перетворення циклу в рекурсивну функцію


Ось покращена версія. Я перетворив цикл for на рекурсивну функцію
ovs

Ах, чудова ідея @ovs
Гравітон

ще коротше Зауважте, що він працюватиме лише з python2
ovs

1

Haskell, 52 45 байт

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

Приклад використання: [-3,3,-3,3,-3,3,-3,3,-3] # 15-> -9009. Спробуйте в Інтернеті!

Як це працює

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

Редагувати: @xnor зберегло 7 байт. Дякую!


Я думаю, що може бути повторена функція zipWith(+)=<<tail.(++[0]), тобто виправити список заздалегідь, а не після цього.
xnor

@xnor: так, це економить багато байтів. Дякую!
німі

Я просто не можу думати про використання =<<тут, це божевільно :)
недолік

@flawr: =<<використовується в контексті функції і визначається як: (=<<) f g x = f (g x) x. Тут ми використовуємо =<<інфікс: (f =<< g) xз f = zipWith(+)і g = tail, що перекладається на zipWith(+) (tail x) x.
німі

Дякую за детальне пояснення, я не знав про функцію монади!
промах

1

CJam , 12 байт

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

Спробуйте в Інтернеті!

Пояснення

Код безпосередньо реалізує процедуру, описану в виклику.

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

Октава , 42 байти

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

Це визначає анонімну функцію. Спробуйте в Інтернеті!

Пояснення

Рішення можна обчислити шляхом багаторазового згортання вхідного масиву та отриманих масивів за допомогою [1, 1]. Але згортання двічі, або тричі, або ... з [1, 1]відповідає згортці один раз з [1, 2 ,1], або [1, 3, 3, 1], або ...; тобто з рядком трикутника Паскаля. Це виходить як антидіагональ матриці Паскаля порядку x+1.


0

JavaScript (ES6), 41 байт

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

Відмінна відповідь Haskell на порт @ xnor. Попереднє 47-байтне рішення.

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.