Eulerian 수 계산


17

오일러 번호 A(n, m) 의 순열의 수를 [1, 2, ..., n]정확하게하는 m요소가 이전 요소보다 크다. 이것들은 상승 이라고도 합니다 . 예를 들어이면 n = 33이 있습니다! = 6 순열[1, 2, 3]

1 2 3
 < <  2 elements are greater than the previous

1 3 2
 < >  1 ...

2 1 3
 > <  1 ...

2 3 1
 < >  1 ...

3 1 2
 > <  1 ...

3 2 1
 > >  0 ...

의 출력 그래서 A(3, m)위해 m에가 [0, 1, 2, 3]있을 것입니다

A(3, 0) = 1
A(3, 1) = 4
A(3, 2) = 1
A(3, 3) = 0

또한 이것은 OEIS 시퀀스 A173018 입니다.

규칙

  • 이것은 이므로 가장 짧은 코드가 승리합니다.
  • 입력 n은 음이 아닌 정수이며 m범위의 정수입니다 [0, 1, ..., n].

테스트 사례

n   m   A(n, m)
0   0   1
1   0   1
1   1   0
2   0   1
2   1   1
2   2   0
3   0   1
3   1   4
3   2   1
3   3   0
4   0   1
4   1   11
4   2   11
4   3   1
4   4   0
5   1   26
7   4   1191
9   5   88234
10  5   1310354
10  7   47840
10  10  0
12  2   478271
15  6   311387598411
17  1   131054
20  16  1026509354985
42  42  0

제한이 n, m있습니까?
Loovjo

제한은 없지만 제출물이 일정 시간 내에 테스트 사례를 완전히 실행할 수있는 것은 아니며 올바른 논리 만 있어야합니다. 가급적이면 최대 20 개의 값을 처리하기 위해 제출을 원하지만 성능 요구 사항 없이는 최대 성능을 발휘할 수있는 무차별 대입 솔루션을 허용하도록 남겨 두었습니다 n = 10.
마일

입력 값에 m> = n, n> 0이있을 수 있습니까?
feersum

"m은 [0, 1, ..., n] 범위의 정수"가 "... [0, 1, ..., n-1]"이 아니어야합니까?
Jonathan Allan

@feersum 솔루션은 m원하는 경우 어떤 것도 지원할 수 있지만 0 <= n 인 0 <= m <= n에 대해서만 유효합니다 .
마일

답변:


9

젤리 , 8 바이트

Œ!Z>2\Sċ

온라인으로 사용해보십시오! (a 동안 소요) 또는 작은 테스트 케이스를 확인 .

작동 원리

Œ!Z>2\Sċ  Main link. Arguments: n, m

Œ!        Generate the matrix of all permutations of [1, ..., n].
  Z       Zip/transpose, placing the permutations in the columns.
   >2\    Compare columns pairwise with vectorizing greater-than.
          This generates a 1 in the column for each rise in that permutation.
      S   Compute the vectorizing sum of the columns, counting the number of rises.
       ċ  Count how many times m appears in the computed counts.

6

자바 스크립트 (ES6), 50 46 45 바이트

f=(n,m,d=n-m)=>m?d&&f(--n,m)*++m+f(n,m-2)*d:1

재귀 공식을 기반으로 :

A(n, m) = (n - m)A(n - 1, m - 1) + (m + 1)A(n - 1, m)    

테스트 사례


4

MATL , 10 바이트

:Y@!d0>s=s

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

설명

예를 들어 입력으로 고려 n=3,m=1 . %그 시점부터 코드를 주석 처리하여 중간 결과를 볼 수있는 심볼을 배치 할 수 있습니다 . 예를 들어, 링크는 첫 번째 단계 이후의 스택을 보여줍니다.

:      % Input n implicitly. Push [1 2 ... n]
       % STACK: [1 2 ... n]
Y@     % Matrix of all permutations, one on each row
       % STACK: [1 2 3; 1 3 2; 2 1 3; 2 3 1; 3 1 2; 3 2 1]
!      % Transpose
       % STACK: [1 1 2 2 3 3; 2 3 1 3 1 2; 3 2 3 1 2 1]
d      % Consecutive differences along each column
       % STACK: [1 2 -1 1 -2 -1; 1 -1 2 -2 1 -1]
0>     % True for positive entries
       % STACK: [1 1 0 1 0 0; 1 0 1 0 1 0]
s      % Sum of each column
       % STACK: [2 1 1 1 1 0]
=      % Input m implicitly. Test each entry for equality with m
       % STACK: [0 1 1 1 1 0]
s      % Sum. Implicitly display
       % STACK: 4

4

CJam ( 21 19 바이트-또는 인수 순서가 비어있는 경우 18)

{\e!f{2ew::>1b=}1b}

이것은 n m스택 을 차지하는 익명 블록 (함수)입니다 . ( m n스택 을 차지하도록 허용 된 경우 \저장 가능). 모든 순열과 필터를 계산하므로 온라인 테스트 스위트 는 다소 제한되어야합니다.

에 대한 근사치를 지적한 Martin에게 감사합니다 filter-with-parameter.

해부

{        e# Define a block. Stack: n m
  \      e#   Flip the stack to give m n
  e!f{   e#   Generate permutations of [0 .. n-1] and map with parameter m
    2ew  e#     Stack: m perm; generate the list of n-1 pairs of consecutive
         e#     elements of perm
    ::>  e#     Map each pair to 1 if it's a rise and 0 if it's a fall
    1b   e#     Count the falls
    =    e#     Map to 1 if there are m falls and 0 otherwise
  }
  1b     e#   Count the permutations with m falls
}

Eulerian 수는 대칭입니다 : E(n, m) = E(n, n-m)이므로 카운트가 떨어지거나 증가하는지는 관계가 없습니다.

효율적으로 : 32 바이트

{1a@{0\+_ee::*(;\W%ee::*W%.+}*=}

온라인 테스트 스위트 .

이것은 전체 행에서 반복을 구현합니다.

{          e# Define a block. Stack: n m
  1a@      e#   Push the row for n=0: [1]; and rotate n to top of stack
  {        e#   Repeat n times:
           e#     Stack: m previous-row
    0\+_   e#     Prepend a 0 to the row and duplicate
    ee::*  e#     Multiply each element by its index
           e#     This gives A[j] = j * E(i-1, j-1)
    (;     e#     Pop the first element, so that A[j] = (j+1) * E(i-1, j)
    \W%    e#     Get the other copy of the previous row and reverse it
    ee::*  e#     Multiply each element by its index
           e#     This gives B[j] = j * E(i-1, i-1-j)
    W%     e#     Reverse again, giving B[j] = (i-j) * E(i-1, j-1)
    .+     e#     Pointwise addition
  }*
  =        e#   Extract the element at index j
}

map :을 사용하여 변수를 피하는 것이 더 짧습니다 {e!f{2ew::>1b=}1e=}. 아니면 그냥 재미를 위해 :{e!f{2ew::>+:-}0e=}
마틴 엔더

물론 그것은 바보였습니다. 1e=제 용액 일 수있다 1b.
Martin Ender

당신은 자신의 인수 순서를 사용할 수 있습니다
마일 마일

3

파이썬, 55 56 바이트

a=lambda n,m:n>=m>0and(n-m)*a(n-1,m-1)-~m*a(n-1,m)or m<1

repl.it의 모든 테스트

OEIS에 재귀 수식을 적용합니다.
참고 +(m+1)*a(n-1,m)로 golfed됩니다 -~m*a(n-1,m).
(부울 나타내는 값을 반환 할 수 있습니다 1또는 0. 반환 또는 .)Truen<0 and m<=0m<0


엣지 케이스를 처리하는 다른 여러 가지 방법이 있습니다. m<1 ? 1 : m==n ? 0 : formula동등 하게 처리하면 충분하다 m%n<1 ? (m<1) : formula. 또는 대안 적으로 m<1 ? (n>=0) : formula.
피터 테일러

감사합니다.
Jonathan Allan

우리의 답변은 매우 유사하고 귀하의 답변이 먼저 게시되고 더 짧으므로 계속해서 삭제하겠습니다.
Loovjo

@Loovjo 비록 약간의 광란의 조정 :( 당신은 어쨌든 나에게서 ^ vote를 얻었다!
Jonathan Allan

3

Mathematica, 59 56 바이트

_~f~0=1
n_~f~m_:=If[m>n,0,(n-m)f[n-1,m-1]+(m+1)f[n-1,m]]

그리고 여기에 글자 그대로 정의를 구현하는 59 바이트 버전이 있습니다.

Count[Count@1/@Sign/@Differences/@Permutations@Range@#,#2]&

f[n_,m_]:=...49 세만되지 ?
Jonathan Allan

@JonathanAllan 잘 모르겠습니다. 기본 사례를 어떻게 처리합니까?
Martin Ender

좋아, 무언가가 캐시되었습니다. 방금 새 워크 시트에서 수행했으며 재귀 제한으로 실패했습니다. :)
Jonathan Allan

46 바이트를 사용하는 공식도 있습니다 Sum[Binomial[#+1,k](#2+1-k)^#(-1)^k,{k,0,#2}]&더 골프를 할 수 있습니다
마일

3

파이썬, 53 바이트

t=lambda n,k:n and(n-k)*t(n-1,k-1)-~k*t(n-1,k)or k==0

OEIS에서 재귀. 때 True처럼 부울 을 출력합니다 .1n==k



2

GameMaker 언어, 62 바이트

이것은 A@Arnauld의 공식에 기반한 재귀 스크립트 입니다.

n=argument0;m=argument1;return (n-m)*A(n-1,m-1)+(m+1)*A(n-1,m)

한동안 보지 못했습니다!
tomsmeding

1

펄, 98 바이트

sub a{my($b,$c)=@_;return$c?$c>$b?0:($b-$c)*a($b-1,$c-1)+($c+1)*a($b-1,$c):1;}print a(@ARGV[0,1]);

Arnauld의 답변과 동일한 속성을 기반으로합니다.


1

R, 72 바이트

OEIS의 논리에 따른 재귀 기능.

A=function(n,m)if(!m)1 else if(m-n)0 else(n-m)*A(n-1,m-1)+(m+1)*A(n-1,m)

이 도전은 내가 시도한 다른 접근 방식들 사이에서 상당히 가깝습니다. 예를 들어, wikipedia 공식을 사용하고 합계를 반복하면 92 바이트가됩니다.

function(n,m){s=0;if(!n)1 else for(k in -1:m+1)s=c(s,(-1)^k*choose(n+1,k)*(m+1-k)^n);sum(s)}

또는 87 바이트의 벡터화 된 버전 :

function(n,m)if(!m)1 else sum(sapply(-1:m+1,function(k)(-1)^k*choose(n+1,k)*(m+1-k)^n))

마지막으로 permute패키지와 함수를 사용하여 모든 순열의 행렬을 생성하는 무차별 대입 솔루션 (103 바이트) allPerms. 이 접근 방식은 작동합니다 n<8.

function(n,m){if(!m)1 else sum(apply(rbind(1:n,permute:::allPerms(n)),1,function(x)sum(diff(x)>0))==m)}

1

라켓 141 바이트

(count(λ(x)(= x m))(for/list((t(permutations(range 1(+ 1 n)))))(count
(λ(x)x)(for/list((i(sub1 n)))(>(list-ref t(+ 1 i))(list-ref t i))))))

언 골프 드 :

(define (f n m)
  (let* ((l (range 1 (add1 n)))                ; create a list till n
         (pl (permutations l))                 ; get all permutations
         (enl (for/list ((t pl))               ; check each permutation; 
                (define rl
                  (for/list ((i (sub1 n)))     ; check if an element is a 'rise'
                    (> (list-ref t (add1 i))
                       (list-ref t i))))
                (count (lambda(x)x) rl))))     ; how many numbers are 'rises'
    (count (lambda(x) (= x m)) enl)))          ; how many permutations had m rises
                                               ; i.e. Eulerian number

테스트 :

(f 3 0)
(f 3 1)
(f 3 2)
(f 3 3)
(f 4 2)
(f 5 1)
(f 7 4)

산출:

1
4
1
0
11
26
1191

1

실제로 , 21 19 바이트

이 답변은 Dennis가 Jelly 답변 에서 사용하는 것과 유사한 알고리즘을 사용합니다 . <내가 계산 하는 동안 원래 정의가 계산 >됩니다. 결국 결국 동등합니다. 골프 제안을 환영합니다. 온라인으로 사용해보십시오!

;R╨`;\ZdX"i>"£MΣ`Mc

언 골핑

         Implicit input m, then n.
;        Duplicate n. Stack: n, n, m
R        Push range [1..n].
╨        Push all n-length permutations of the range.
`...`M   Map the following function over each permutation p.
  ;\       Duplicate and rotate p so that we have a list of the next elements of p.
  Z        Zip rot_p and p.
           (order of operands here means the next element is first,
            so we need to use > later)
  dX       Remove the last pair as we don't compare the last and first elements of the list.
  "i>"£    Create a function that will flatten a list and check for a rise.
  M        Map that function over all the pairs.
  Σ        Count how many rises there are in each permutation.
c        Using the result of the map and the remaining m, 
          count how many permutations have m rises.
         Implicit return.


0

J, 28 바이트

+/@((!>:)~*(^~#\.)*_1^])i.,]

공식을 사용합니다

공식

용법

   f =: +/@((!>:)~*(^~#\.)*_1^])i.,]
   0 f 0
1
   1 f 0
1
   1 f 1
0
   (f"+i.,]) 6
1 57 302 302 57 1 0
   20x f 16x
1026509354985

설명

+/@((!>:)~*(^~#\.)*_1^])i.,]  Input: n (LHS), m (RHS)
                        i.    Range [0, 1, ..., m-1]
                           ]  Get m
                          ,   Join to get k = [0, 1, ..., m]
                      ]       Get k
                   _1^        Raise -1 to each in k
              #\.               Get the length of each suffix of k
                                Forms the range [m+1, m, ..., 2, 1]
            ^~                  Raise each value by n
                  *           Multiply elementwise with (-1)^k
    (   )~                      Commute operators
      >:                        Increment n
     !                          Binomial coefficient, C(n+1, k)
          *                   Multiply elementwise
+/@                           Reduce by addition to get the sum and return
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.