Hitung nomor Euler

17

Nomor Euler A(n, m) adalah jumlah permutasi [1, 2, ..., n]di mana melemen persis lebih besar dari elemen sebelumnya. Ini juga disebut naik . Misalnya, jika n = 3, ada 3! = 6 permutasi dari[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 ...

Jadi output untuk A(3, m)untuk mdi [0, 1, 2, 3]akan

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

Juga, ini adalah urutan OEIS A173018 .

Aturan

  • Ini adalah sehingga kode terpendek menang.
  • Input nakan berupa bilangan bulat negatif dan makan menjadi bilangan bulat dalam kisaran [0, 1, ..., n].

Uji Kasus

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
mil
sumber
Adakah batasan pada n, m?
Loovjo
Tidak ada batasan, tetapi itu tidak diperlukan bahwa kiriman Anda dapat sepenuhnya menjalankan kasus uji dalam waktu tertentu, hanya memiliki logika yang benar. Lebih disukai, saya ingin pengiriman untuk menangani nilai hingga 20, tapi saya meninggalkannya tanpa persyaratan kinerja untuk memungkinkan solusi brute-force yang mungkin hanya berfungsi hingga n = 10.
mil
Bisakah input memiliki m> = n, n> 0?
feersum
Tidakkah seharusnya, "m akan menjadi bilangan bulat dalam kisaran [0, 1, ..., n]" menjadi "... [0, 1, ..., n-1]"?
Jonathan Allan
@feersum Solusi Anda dapat mendukung apa pun mjika diinginkan, tetapi saya hanya meminta valid untuk 0 <= m <= n dengan 0 <= n .
mil

Jawaban:

9

Jelly , 8 byte

Œ!Z>2\Sċ

Cobalah online! (perlu beberapa saat) atau verifikasi kasus uji yang lebih kecil .

Bagaimana itu bekerja

Œ!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.
Dennis
sumber
6

JavaScript (ES6), 50 46 45 byte

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

Berdasarkan rumus rekursif:

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

Uji kasus

Arnauld
sumber
4

MATL , 10 byte

:Y@!d0>s=s

Cobalah online!

Penjelasan

Pertimbangkan sebagai contoh masukan n=3,m=1 . Anda dapat menempatkan %simbol untuk mengomentari kode dari titik itu dan seterusnya dan dengan demikian melihat hasil antara. Misalnya, tautan menampilkan tumpukan setelah langkah pertama.

:      % 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
Luis Mendo
sumber
4

CJam ( 21 19 byte - atau 18 jika urutan argumen gratis)

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

Ini adalah blok anonim (fungsi) yang mengambil n mtumpukan. (Jika diizinkan untuk mengambil m ntumpukan maka \dapat disimpan). Itu menghitung semua permutasi dan filter, sehingga rangkaian uji online harus agak terbatas.

Terima kasih kepada Martin karena menunjukkan perkiraan filter-with-parameter.

Pembedahan

{        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
}

Perhatikan bahwa angka Euler adalah simetris:, E(n, m) = E(n, n-m)jadi tidak relevan apakah Anda menghitung jatuh atau naik.

Secara efisien: 32 byte

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

Test suite online .

Ini mengimplementasikan pengulangan pada seluruh baris.

{          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
}
Peter Taylor
sumber
Itu lebih pendek untuk menghindari variabel dengan menggunakan peta: {e!f{2ew::>1b=}1e=}. Atau hanya untuk bersenang-senang:{e!f{2ew::>+:-}0e=}
Martin Ender
Tentu saja itu bodoh. The 1e=dalam solusi pertama dapat 1b.
Martin Ender
Anda diizinkan menggunakan urutan argumen Anda sendiri
mil
3

Python, 55 56 byte

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

Semua tes di repl.it

Menerapkan rumus rekursif pada OEIS.
Perhatikan bahwa +(m+1)*a(n-1,m)golf untuk -~m*a(n-1,m).
(Dapat mengembalikan nilai boolean untuk mewakili 1atau 0. Mengembalikan Trueketika n<0 and m<=0atau m<0.)

Jonathan Allan
sumber
Ada berbagai cara lain untuk menangani kasing tepi. Itu sudah cukup untuk menangani m<1 ? 1 : m==n ? 0 : formula, setara m%n<1 ? (m<1) : formula; atau sebagai alternatif m<1 ? (n>=0) : formula.
Peter Taylor
Saya mengerti, baru saja memperbarui terima kasih
Jonathan Allan
Karena jawaban kami sangat mirip, dan jawaban Anda diposting lebih dulu (dan lebih pendek), saya akan melanjutkan dan menghapus jawaban saya.
Loovjo
@Loovjo Sedikit tweaking panik :( Anda tetap mendapat suara ^ dari saya!
Jonathan Allan
3

Mathematica, 59 56 byte

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

Dan di sini adalah versi 59 byte yang mengimplementasikan definisi secara lebih harfiah:

Count[Count@1/@Sign/@Differences/@Permutations@Range@#,#2]&
Martin Ender
sumber
Kenapa tidak hanya f[n_,m_]:=...untuk 49?
Jonathan Allan
@ Jonathan Allan Saya tidak yakin saya mengerti. Bagaimana cara menangani kasing?
Martin Ender
OK, ada sesuatu yang di-cache - lakukan saja di lembar kerja baru dan gagal dengan batas rekursi. :)
Jonathan Allan
Ada juga formula yang menggunakan 46 byte Sum[Binomial[#+1,k](#2+1-k)^#(-1)^k,{k,0,#2}]&yang mungkin untuk bermain golf lebih
mil
3

Python, 53 byte

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

Rekursi dari OEIS. Output Boolean Trueseperti 1saat n==k.

Tidak
sumber
2

MATLAB / Oktaf, 40 byte

@(n,m)sum(sum(diff((perms(1:n))')>0)==m)

Ini adalah port jawaban MATL saya, dalam bentuk fungsi anonim. Sebut saja sebagai ans(7,4).

Cobalah di Ideone .

Luis Mendo
sumber
2

Bahasa GameMaker, 62 byte

Ini adalah skrip rekursif Aberdasarkan rumus @ Arnauld.

n=argument0;m=argument1;return (n-m)*A(n-1,m-1)+(m+1)*A(n-1,m)
Timtech
sumber
Belum melihat ITU dalam beberapa saat!
mulai
1

Perl, 98 byte

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

Berdasarkan properti yang sama dengan jawaban Arnauld.

Gabriel Benamy
sumber
1

R, 72 byte

Fungsi rekursif mengikuti logika pada 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)

Tantangan ini ternyata cukup dekat antara berbagai pendekatan yang saya coba. Misalnya, menggunakan rumus wikipedia dan mengulang jumlah menghasilkan 92 byte:

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

atau versi vektor untuk 87 byte:

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

dan akhirnya solusi brute force (103 bytes) yang menghasilkan matriks dari semua permutasi dengan menggunakan permutepaket dan fungsinya allPerms. Pendekatan ini hanya bekerja sampai n<8saat ini.

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

Racket 141 byte

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

Tidak Disatukan:

(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

Pengujian:

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

Keluaran:

1
4
1
0
11
26
1191
juga
sumber
1

Sebenarnya , 21 19 byte

Jawaban ini menggunakan algoritma yang mirip dengan yang digunakan Dennis dalam jawaban Jelly- nya . Definisi asli penting <saat saya hitung >. Ini akhirnya menjadi setara pada akhirnya. Saran bermain golf diterima. Cobalah online!

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

Tidak melakukanolf

         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.
Sherlock9
sumber
0

J, 28 byte

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

Menggunakan formula

rumus

Pemakaian

   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

Penjelasan

+/@((!>:)~*(^~#\.)*_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
mil
sumber