คำนวณหมายเลข Eulerian


17

จำนวน Eulerian 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)for min [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]"?
Jonathan Allan

@feersum วิธีการแก้ปัญหาของคุณสามารถสนับสนุนการใด ๆmได้ถ้าต้องการ แต่ฉันเพียงต้องการที่จะเป็นที่ถูกต้องสำหรับ 0 <= <= 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=}
Martin Ender

แน่นอนว่าเป็นคนโง่ ในการแก้ปัญหาครั้งแรกที่สามารถ1e= 1b
Martin Ender

คุณได้รับอนุญาตให้ใช้คำสั่งโต้แย้งของคุณเอง
ไมล์

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หรืออีกวิธีหนึ่ง
Peter Taylor

ฉันเข้าใจแล้วเพิ่งจะอัปเดตขอบคุณ
Jonathan Allan

เนื่องจากคำตอบของเราคล้ายกันมากและมีการโพสต์ของคุณก่อน (และสั้นกว่า) ฉันจะดำเนินการต่อไปและลบของฉันออก
Loovjo

@ Loovjo เล็กน้อย tweaking คลั่งแม้ว่า :( คุณได้รับการโหวต ^ จากฉันต่อไป!
Jonathan Allan

3

มาติกา 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 เท่านั้น
Jonathan Allan

@JanathanAllan ฉันไม่แน่ใจว่าฉันเข้าใจ ที่จัดการกรณีฐานได้อย่างไร
Martin Ender

ตกลงบางสิ่งถูกแคช - ทำในเวิร์กชีทใหม่และล้มเหลวด้วยการ จำกัด การเรียกซ้ำ :)
Jonathan Allan

นอกจากนี้ยังมีสูตรที่ใช้ 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เป็นเมื่อ1n==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)}

หรือเวอร์ชัน vectorized สำหรับ 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 bytes) ที่สร้างเมทริกซ์ของพีชคณิตทั้งหมดโดยใช้แพคเกจและฟังก์ชั่น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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.