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

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.

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


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

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
}

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


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

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.


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 .


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)

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.


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

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

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.


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.