オイラー数を計算する


17

オイラー数 A(n, m)の順列の数であり、[1, 2, ..., n]正確にここでm要素が前の要素よりも大きいです。これらはライズとも呼ばれます。たとえば、の場合n = 3、3!= 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]」ではありませんか?
ジョナサンアラン

@feersumソリューションはm必要に応じてサポートできますが、0 <= m <= nで0 <= nの場合にのみ有効であることを要求します。
マイル

回答:


9

ゼリー、8 バイト

Œ!Z>2\Sċ

オンラインでお試しください!(少し時間がかかります)、またはより小さいテストケースを確認します。

使い方

Œ!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

JavaScript(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=3m=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
}

オイラー数は対称的であることに注意してください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
}

これは、マップを使用して、変数を避けるために短いです:{e!f{2ew::>1b=}1e=}。または単に楽しみのために:{e!f{2ew::>+:-}0e=}
マーティンエンダー

もちろんそれは愚かだった。1e=最初のソリューションにすることができ1b
マーティンエンダー

独自の引数の順序を使用することができます
マイル

3

Python、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)ゴルフされていることに注意してください-~m*a(n-1,m)
1またはを表すブール値を0返すことTruen<0 and m<=0できm<0ます。またはを返します。)


エッジケースを処理する他のさまざまな方法があります。m<1 ? 1 : m==n ? 0 : formula同等に処理すれば十分m%n<1 ? (m<1) : formulaです。または、代わりにm<1 ? (n>=0) : formula
ピーターテイラー

私は感謝の更新、それを得た
ジョナサン・アラン

私たちの回答は非常に似ており、あなたの回答が最初に投稿された(そしてより短い)ので、先に進んで私のものを削除します。
Loovjo

@Loovjoでも必死に微調整を少し:(とにかく私から^ voteを得た!
ジョナサンアラン

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のためだけではありませんか?
ジョナサンアラン

@JonathanAllan私は理解しているかどうかわかりません。それは基本ケースをどのように扱いますか?
マーティンエンダー

OK、何かがキャッシュされました-新しいワークシートでそれをしただけで、再帰制限で失敗しました。:)
ジョナサンアラン

Sum[Binomial[#+1,k](#2+1-k)^#(-1)^k,{k,0,#2}]&さらにゴルフをするために46バイトを使用する式もあります
マイル

3

Python、53バイト

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

OEISからの再帰。ブール値True1when として出力しn==kます。



2

GameMaker Language、62バイト

これは、A@ Arnauldの式に基づいた再帰的なスクリプトです。

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

しばらく見ていない!
tomsmeding

1

Perl、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)

この課題は、私が試したさまざまなアプローチの間に非常に近いことが判明しました。たとえば、ウィキペディアの式を使用して合計をループすると、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バイト)allPermsn<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バイト

この回答では、デニスがジェリーの回答で使用しているものと同様のアルゴリズムを使用しています。元の定義は<、カウント中にカウントされます>。これは最終的に同等になります。ゴルフの提案を歓迎します。オンラインでお試しください!

;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.