오일러 방법 구현


9

이 과제의 목표는 오일러 방법 을 사용 하여 f (n) (x) = c 형식의 미분 방정식의 해를 근사화하는 것입니다 .

입력은 n 번째 값이 f (n) (0) 의 값을 나타내는 정수 목록입니다 . 첫 번째 정수는 f (0)이고 두 번째 정수는 f '(0)입니다. 이 목록의 마지막 정수는 상수이며 항상 동일하게 유지됩니다.

또한 입력으로 제공되는 양의 (0이 아닌) 정수 x 는 목표 값을 나타냅니다 (f (x)를 추정하려고합니다). 오일러 방법의 단계 크기는 항상 1입니다. 따라서 총 x 단계를 수행 해야합니다 .

당신은 오일러의 방법 unfamliar 경우, 여기에 입력에 대한 설명과 상세한 예제 [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입니다. ††

입력 목록은 항상 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

† :이 상황에서 근사법을 사용하는 것은 실제로 어리석은 일입니다. 그러나이 도전의 목적을 위해 가장 간단한 기능이 선택되었습니다.

†† : 실제 값은 -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이되기 때문에 입력 값이 오른쪽에 무한히 많은 0으로 채워지는 것이 이상적입니다. 우리는를 0취할 때 를 추가하여 이것을 시뮬레이션 합니다 tail.

이상한 대체 41 :

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


3

젤리 , 6 5 바이트

Ḋ+$¡Ḣ

온라인으로 사용해보십시오!

@Doorknob 덕분에 -1 바이트

설명

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

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

작동 방식 (파이썬 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 바이트 교대

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

작동 방식 (파이썬 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. 반복되는 뉴턴 방법 (예제 참조)이 파스칼 삼각형의 구성과 정확히 동일하게 작동하므로 직관적입니다.

온라인으로 사용해보십시오!

루프를 재귀 함수로 변환하여 22 바이트 를 줄인 ov 덕분


다음 은 개선 된 버전입니다. 나는 재귀 함수에 for 루프를 변환
OVS

아, 좋은 아이디어 @ovs
Graviton

더 짧음 python2에서만 작동합니다.
ovs

1

하스켈, 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 : 예, 많은 바이트를 절약합니다. 감사!
nimi

나는 단지 =<<여기 의 사용에 대해 내 마음을 감쌀 수 없다 . 이것은 미친 것이다 :)
flawr

@flawr : =<<는 함수 컨텍스트에서 사용되며 다음과 같이 정의됩니다 (=<<) f g x = f (g x) x. 여기에 우리가 사용 =<<: 중위를 (f =<< g) x함께 f = zipWith(+)하고 g = tail로 변환하는 zipWith(+) (tail x) x.
nimi

자세한 설명을 주셔서 감사합니다. 모나드 기능을 알지 못했습니다!
flawr

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

실제로 7 바이트

;lr(♀█*

온라인으로 사용해보십시오!

작동 원리

;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

옥타브 , 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

자바 스크립트 (ES6), 41 바이트

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

@xnor 포트의 우수한 Haskell 답변. 이전 47 바이트 솔루션.

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


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.