Calcola il numero euleriano


17

Il numero euleriano A(n, m) è il numero di permutazioni [1, 2, ..., n]in cui esattamente gli melementi sono maggiori dell'elemento precedente. Questi sono anche chiamati aumenti . Ad esempio, se n = 3ce ne sono 3! = 6 permutazioni di[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 ...

Quindi saranno le uscite per A(3, m)for min[0, 1, 2, 3]

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

Inoltre, questa è la sequenza OEIS A173018 .

Regole

  • Questo è quindi vince il codice più corto.
  • L'input nsarà un numero intero non negativo e msarà un numero intero nell'intervallo [0, 1, ..., n].

Casi test

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

Qualche limite su n, m?
Loovjo,

Non vi è alcun limite, ma non è necessario che l'invio sia in grado di eseguire completamente un caso di test in un determinato periodo di tempo, solo avere la logica corretta. Preferibilmente, vorrei che gli invii gestissero valori fino a 20, ma l'ho lasciato senza un requisito prestazionale per consentire soluzioni a forza bruta che potrebbero funzionare solo fino a n = 10.
miglia

L'ingresso può avere m> = n, n> 0?
feersum

Non dovrebbe, "m sarà un numero intero nell'intervallo [0, 1, ..., n]" be "... [0, 1, ..., n-1]"?
Jonathan Allan,

@feersum La tua soluzione può supportare qualsiasi mse lo desideri, ma ho solo bisogno che sia valida per 0 <= m <= n con 0 <= n .
miglia

Risposte:


9

Gelatina , 8 byte

Œ!Z>2\Sċ

Provalo online! (richiede un po 'di tempo) o verifica i casi di test più piccoli .

Come funziona

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

Basato sulla formula ricorsiva:

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

Casi test


4

MATL , 10 byte

:Y@!d0>s=s

Provalo online!

Spiegazione

Si consideri come esempio ingressi n=3,m=1 . È possibile posizionare un %simbolo per commentare il codice da quel punto in poi e quindi vedere i risultati intermedi. Ad esempio, il collegamento mostra lo stack dopo il primo passaggio.

:      % 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 - o 18 se l'ordine degli argomenti è gratuito)

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

Questo è un blocco (funzione) anonimo che accetta n mlo stack. (Se è permesso prendere m nin pila, allora \può essere salvato). Calcola tutte le permutazioni e i filtri, quindi la suite di test online deve essere piuttosto limitata.

Grazie a Martin per averci indicato un'approssimazione filter-with-parameter.

Dissezione

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

Si noti che i numeri di Eulerian sono simmetrici:, E(n, m) = E(n, n-m)quindi è irrilevante se si contano cadute o aumenti.

In modo efficiente: 32 byte

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

Suite di test online .

Questo implementa la ricorrenza su intere righe.

{          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 'più breve per evitare la variabile utilizzando una mappa: {e!f{2ew::>1b=}1e=}. O solo per divertimento:{e!f{2ew::>+:-}0e=}
Martin Ender,

È stato stupido, ovviamente. La 1e=prima soluzione può essere 1b.
Martin Ender,

Ti è permesso usare il tuo ordine argomento
miglia

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

Tutti i test su repl.it

Applica la formula ricorsiva su OEIS.
Si noti che +(m+1)*a(n-1,m)è giocato a -~m*a(n-1,m).
(Può restituire valori booleani per rappresentare 1o 0. Restituisce Truequando n<0 and m<=0o m<0.)


Esistono vari altri modi per gestire i casi limite. Basta gestire m<1 ? 1 : m==n ? 0 : formula, equivalentemente m%n<1 ? (m<1) : formula; o in alternativa m<1 ? (n>=0) : formula.
Peter Taylor,

Ho capito, solo aggiornando grazie
Jonathan Allan,

Poiché le nostre risposte sono molto simili e le tue sono state pubblicate per prime (ed è più breve), andrò avanti ed eliminerò la mia.
Loovjo,

@Loovjo Un po 'di modifiche frenetiche però :( Hai ottenuto comunque un ^ voto da parte mia!
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]]

Ed ecco una versione da 59 byte che implementa la definizione in modo più letterale:

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

Perché non solo f[n_,m_]:=...per 49?
Jonathan Allan,

@JonathanAllan Non sono sicuro di aver capito. In che modo gestisce la custodia di base?
Martin Ender,

OK, qualcosa è stato memorizzato nella cache: l'ho appena fatto in un nuovo foglio di lavoro e non è riuscito con il limite di ricorsione. :)
Jonathan Allan,

C'è anche la formula che utilizza 46 byte Sum[Binomial[#+1,k](#2+1-k)^#(-1)^k,{k,0,#2}]&che potrebbero essere possibili per giocare a golf di più
miglia

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

Ricorsione da OEIS. Output booleano Truecome 1quando n==k.


2

MATLAB / Octave, 40 byte

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

Questa è una porta della mia risposta MATL, sotto forma di una funzione anonima. Chiamalo come ans(7,4).

Provalo su Ideone .


2

Lingua GameMaker, 62 byte

Questo è uno script ricorsivo Abasato sulla formula di @ Arnauld.

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

Non lo vedo da un po '!
tomsmeding

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

Basato sulla stessa proprietà della risposta di Arnauld.


1

R, 72 byte

Funzione ricorsiva secondo la logica su 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)

Questa sfida si è rivelata abbastanza vicina tra i diversi approcci che ho provato. Ad esempio, l'utilizzo della formula di Wikipedia e il ciclo sulla somma hanno comportato 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)}

o la versione vettoriale per 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))

e infine la soluzione di forza bruta (103 byte) che genera una matrice di tutte le permutazioni usando il permutepacchetto e la funzione allPerms. Questo approccio funziona solo fino a che 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

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

Ungolfed:

(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

test:

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

Produzione:

1
4
1
0
11
26
1191

1

In realtà , 21 19 byte

Questa risposta usa un algoritmo simile a quello che Dennis usa nella sua risposta Jelly . La definizione originale conta <mentre io conto >. Questo finisce per essere equivalente alla fine. Suggerimenti di golf benvenuti. Provalo online!

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

Ungolfing

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

Usa la formula

formula

uso

   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

Spiegazione

+/@((!>:)~*(^~#\.)*_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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.