Вычислить эйлерово число


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=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в стек, то \можно сохранить). Он вычисляет все перестановки и фильтры, поэтому набор онлайн-тестов должен быть довольно ограниченным.

Спасибо Мартину за указание на приближение к 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. Возвращается, Trueкогда n<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 Немного безумной настройки, хотя :( В любом случае, вы получили ^ голос от меня!
— Джонатан Аллан

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 Я не уверен, что понимаю. Как это обрабатывает базовый случай?
— Мартин Эндер

Хорошо, что-то было кэшировано - просто сделал это на новом листе, и это не удалось с пределом рекурсии. :)
— Джонатан Аллан

Существует также формула, которая использует 46 байтов, Sum[Binomial[#+1,k](#2+1-k)^#(-1)^k,{k,0,#2}]&которые могут быть возможны для игры в гольф
— мили

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. Выходы логические Trueкак и 1когда n==k.



2

Язык GameMaker, 62 байта

Это рекурсивный скрипт, Aоснованный на формуле @ Арно.

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

Этого давно не видел!
— Томсминг

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

На основании того же свойства, что и ответ Арно.


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

и, наконец, решение методом грубой силы (103 байта), которое генерирует матрицу всех перестановок с использованием permuteпакета и функции 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))))))

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

Тестирование:

(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

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 байт

+/@((!>:)~*(^~#\.)*_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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.