Thực hiện phương pháp Euler


9

Mục tiêu của thử thách này là sử dụng phương pháp Euler để tính gần đúng nghiệm của phương trình vi phân có dạng f (n) (x) = c.

Đầu vào sẽ là một danh sách các số nguyên trong đó giá trị thứ n đại diện cho giá trị của f (n) (0). Số nguyên đầu tiên là f (0), số thứ hai là f '(0), v.v. Số nguyên cuối cùng trong danh sách này là hằng số và sẽ luôn giữ nguyên.

Cũng được cung cấp dưới dạng đầu vào sẽ là số nguyên dương (không khác) x , đại diện cho giá trị đích (bạn đang cố ước tính f (x)). Kích thước bước cho phương pháp Euler sẽ luôn là 1. Do đó, bạn sẽ cần thực hiện tổng số bước x .

Nếu bạn không hài lòng với phương pháp của Euler, đây là một ví dụ chi tiết với lời giải thích cho đầu vào [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

Về cơ bản, mỗi ô trong bảng được tạo là tổng của ô bên trên và ô bên trên và bên phải. Vậy, f (a) = f (a-1) + f '(a-1); f '(a) = f' (a-1) + f '' (a-1); và f '' (a) = f '' (a-1) + f '' '(a-1). Câu trả lời cuối cùng là f (8) -8. ††

Danh sách đầu vào sẽ luôn chứa 2 hoặc nhiều phần tử, tất cả các phần tử này sẽ có giá trị tuyệt đối nhỏ hơn 10. x 1 cũng được đảm bảo. Đầu ra là một số nguyên duy nhất, xấp xỉ của f (x). Đầu vào có thể được thực hiện theo một trong hai thứ tự (danh sách trước x hoặc x trước danh sách). x cũng có thể là thành phần đầu tiên hoặc cuối cùng của danh sách, nếu muốn.

Các trường hợp thử nghiệm:

[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

: Đáng chú ý là sử dụng một phương pháp gần đúng trong tình huống này, trên thực tế, là ngu ngốc. tuy nhiên, chức năng đơn giản nhất có thể đã được chọn cho các mục đích của thử thách này.

: Giá trị thực tế xảy ra là -25⅓, sẽ đủ điều kiện xấp xỉ này là "không tốt lắm".



Câu trả lời:


3

Haskell , 38 byte

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

Hãy thử trực tuyến!

Cải thiện từ 39 byte:

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

Đệ quy biểu thị đầu ra l%n. Di chuyển lên tương ứng với giảm dần nvà di chuyển sang phải tương ứng với việc tail lthay đổi tất cả các thành phần danh sách một khoảng trống bên trái. Vì vậy, đầu ra l%nlà giá trị ở trên l%(n-1), cộng với giá trị ở trên và bên phải(tail l)%(n-1)

Trường hợp cơ bản n==0là lấy phần tử danh sách đầu tiên.

Lý tưởng nhất, đầu vào sẽ được đệm với vô số số 0 ở bên phải, vì các đạo hàm của đa thức cuối cùng trở thành số không. Chúng tôi mô phỏng điều này bằng cách nối thêm 0khi chúng tôi lấy tail.

Lạ thay 41:

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


3

Thạch , 6 5 byte

Ḋ+$¡Ḣ

Hãy thử trực tuyến!

-1 byte nhờ @Doorknob

Giải trình

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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

Giải pháp 13 byte trước đó

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

{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

Toán học, 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

Yêu toán học cho thử thách này.

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

Cách thức hoạt động (chỉ hoạt động với 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

Hãy thử trực tuyến!

Thay thế 100 byte với việc sử dụng tam giác 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)])

Cách thức hoạt động (hoạt động cho python 2 và 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

Công thức này hoạt động bằng cách lập bản đồ hệ số của hàng xcủa pascal tam giác vào mảng. Mỗi phần tử của tam giác pascals được xác định bởi chức năng chọn của hàng và chỉ mục. Tổng của mảng mới này tương đương với đầu ra tại x. Nó cũng trực quan khi quá trình lặp lại của phương pháp newtons (được hiển thị trong ví dụ) hoạt động chính xác như việc xây dựng tam giác pascals.

Hãy thử trực tuyến!

Xin chân thành cảm ơn các ovs đã giảm 22 byte bằng cách chuyển đổi vòng lặp thành hàm đệ quy


Đây là một phiên bản cải tiến. Tôi đã chuyển đổi vòng lặp for thành một hàm đệ quy
ovs

À, ý tưởng tuyệt vời @ovs
Graviton

thậm chí ngắn hơn Lưu ý rằng nó sẽ chỉ hoạt động với python2
ovs

1

Haskell, 52 45 byte

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

Ví dụ sử dụng: [-3,3,-3,3,-3,3,-3,3,-3] # 15-> -9009. Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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

Chỉnh sửa: @xnor lưu 7 byte. Cảm ơn!


Tôi nghĩ rằng chức năng lặp có thể zipWith(+)=<<tail.(++[0]), tức là sửa danh sách trước chứ không phải sau đó.
xnor

@xnor: vâng, nó tiết kiệm rất nhiều byte. Cảm ơn!
nimi

Tôi chỉ không thể bao bọc tâm trí của mình xung quanh việc sử dụng =<<ở đây, điều này thật điên rồ :)
flawr

@flawr: =<<được sử dụng trong ngữ cảnh hàm và được định nghĩa là : (=<<) f g x = f (g x) x. Ở đây chúng tôi sử dụng =<<infix: (f =<< g) xwith f = zipWith(+)g = tail, dịch nghĩa là zipWith(+) (tail x) x.
nimi

Cảm ơn bạn đã giải thích chi tiết, tôi đã không nhận thức được chức năng đơn nguyên!
flawr

1

CJam , 12 byte

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

Hãy thử trực tuyến!

Giải trình

Mã trực tiếp thực hiện các thủ tục được mô tả trong thử thách.

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

Trên thực tế , 7 byte

;lr(♀█*

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

;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

Octave , 42 byte

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

Điều này xác định một chức năng ẩn danh. Hãy thử trực tuyến!

Giải trình

Giải pháp có thể được tính toán bằng cách liên tục kết hợp mảng đầu vào và mảng kết quả với [1, 1]. Nhưng kết hợp hai lần, hoặc ba lần, hoặc ... [1, 1]tương ứng với kết hợp một lần với [1, 2 ,1], hoặc [1, 3, 3, 1], hoặc ...; đó là, với một hàng của tam giác Pascal. Điều này có được như là đường chéo của ma trận Pascal theo thứ tự x+1.


0

JavaScript (ES6), 41 byte

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

Câu trả lời Haskell tuyệt vời của cảng @ xnor. Giải pháp 47 byte trước đó.

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


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.