Zählung der Anzahl der Sperrwälder auf der Möbiusleiter der Länge n


13

Die OEIS-Sequenz A020872 zählt die Anzahl der eingeschränkten Wälder auf der Möbius-Leiter M n .

Die Herausforderung

Die Herausforderung besteht darin, ein Programm zu schreiben, das eine Ganzzahl als Eingabe verwendet n > 1und A020872(n)die Anzahl der eingeschränkten Gesamtstrukturen auf der Möbius-Leiter M n zurückgibt . Das ist , also gewinnt der kürzeste Code. (Ein hintergründiges Motiv ist es, die Länge dieser Sequenz vielleicht um ein bisschen zu verlängern.)

Definitionen

Eine eingeschränkte Gesamtstruktur ist eine Partition des Diagramms, sodass jeder Teil entweder ein (ungerichteter) Pfad oder ein isolierter Scheitelpunkt ist.

Die Möbius-Leiter M n ist eine graphische Darstellung des 2n-Gons mit Diagonalen zwischen allen gegenüberliegenden Eckpunkten.

Beispiel

Hier sind die 34 eingeschränkten Wälder auf M 2 (ein Quadrat mit gezeichneten Diagonalen). Beachten Sie, dass das erste Diagramm in vier isolierte Scheitelpunkte, das zweite in einen Pfad und zwei isolierte Scheitelpunkte usw. unterteilt ist. A020872 (2)


1
Testfälle 2-12: 34, 241, 1582, 10204, 65197, 415076, 2638366, 16759249, 106427154, 675771276, 4290678337. Ich bin mir nicht sicher, warum 1bei output auch keine Eingabe erforderlich ist 2.
Peter Taylor

@PeterTaylor, Vielen Dank, dass Sie diese Begriffe zu OEIS hinzugefügt haben! Ich habe die Eingabe ausgeschlossen, 1da M_1 im Wikipedia-Artikel nicht klar definiert ist. (Insbesondere hat es entweder mehrere Kanten oder es ist kein kubischer Graph.)
Peter Kagey

1
Das klingt tatsächlich wie ein guter Kandidat für eine fastest-codeoder eine fastest-algorithmHerausforderung.
Mypetlion

1
Weitere Testfälle ( Generationscode ): 13 bis 17 sind27242281044, 172964658642, 1098170541121, 6972388689086, 44268329738124
Peter Taylor

1
Richtig, ich denke, Ihr Hintergedanke ist mehr als zufrieden.
Peter Taylor

Antworten:


10

CJam ( 58 56 Zeichen)

Einige Zeichen sind nicht druckbar, und eines ist eine Registerkarte, die von der StackExchange-Software entstellt wird:

"¶3¬î¿Á·    7ÛÈmÈÚÚ¡"256b454b212f-{__W%.*A<1b+}qi*-4=

Online-Demo . Dies wird für n = 400 in ungefähr drei Sekunden online ausgeführt.

Codiert von xxd:

0000000: 22b6 0233 93ac eebf c1b7 0609 3794 dbc8  "..3........7...
0000010: 6dc8 1015 dada a122 3235 3662 3435 3462  m......"256b454b
0000020: 3231 3266 2d7b 5f5f 5725 2e2a 413c 3162  212f-{__W%.*A<1b
0000030: 2b7d 7169 2a2d 343d                      +}qi*-4=

Erläuterung

Eine Möbiusleiter ist im Grunde eine Leiter mit zwei zusätzlichen Kanten. Bei einem eingeschränkten Wald auf einer Leiter kann er auf der Möbius-Leiter in 1 bis 4 eingeschränkte Wälder angehoben werden. Die Kanten können hinzugefügt werden, sofern kein Scheitelpunkt mit Grad 3 oder ein Zyklus erstellt wird. Die Grade der vier Ecken und ihre Verbindungen bilden 116 Klassen von eingeschränkten Wäldern auf der Leiter, obwohl einige von ihnen aufgrund von Symmetrien des Rechtecks ​​gleichwertig sind. Ich habe ein Programm geschrieben, um die Erweiterungen einer Leiter der Länge n zu einer der Länge n + 1 zu analysieren, und dann die Klassen in 26 Äquivalenzklassen zusammengeführt. Dies ergibt eine geschlossene Form

[1111]T[1220121123410010]n2[0100]+

[221111122]T[211111111101001010002010000001010000000100001110000011001000011322112142000100002]n2[002200000]+

[1244113222344]T[0001000000100020010000000001201101101111004003002000000000001021001000000000111001002001000012000010001201001000000000002002001000000000000010000000000102200230110210124]n2[1011201000121]

so values can be computed fast by taking three linear recurrences and then adding them, but this isn't looking very golfy.

However, if we take the irreducible factors of the various characteristic polynomials and multiply together one of each (ignoring multiplicity) we get a polynomial of degree 10 which gives a working single linear recurrence.

Constructive approach (58 chars)

qi:Q2*,Wa*e!{Wa/{_W%e<}%$}%_&{{,1>},2few:~{:-z(Q(%}%0-!},,

Online demo. It will run online for n=2 without problems and for n=3 with a bit of patience. For n=1 it crashes, but since OP has chosen to exclude that case from the requirements it's not a fundamental problem.

Dissection

qi:Q          e# Take input from stdin, parse to int, store in Q
2*,Wa*e!      e# Take all permutations of (0, -1, 1, -1, 2, -1, ..., -1, 2*Q-1)
{             e# Map to canonical form...
  Wa/         e#   Split around the -1s
  {_W%e<}%    e#   Reverse paths where necessary to get a canonical form
  $           e#   Sort paths
}%
_&            e# Filter to distinct path sets
{             e# Filter to path sets with valid paths:
  {,1>},      e#   Ignore paths with fewer than two elements (can't be invalid; break 2ew)
  2few:~      e#   Break paths into their edges
  {:-z(Q(%}%  e#   The difference between the endpoints of an edge should be +/-1 or Q (mod 2Q)
              e#   So their absolute values should be 1, Q, 2Q-1.
              e#   d => (abs(d)-1) % (Q-1) maps those differences, and no other possible ones, to 0
              e#   NB {:-zQ(%}% to map them all to 1 would save a byte, but wouldn't work for Q=2
  0-!         e#   Test that all values obtained are 0
},
,             e# Count the filtered distinct path sets

A more efficient version takes 98 bytes:

qi2*:Q{a{__0=[1Q2/Q(]f+Qf%_&1$-\f{+E}~}:E~}/]{_W%>!},:MW=0{_{M\f{__3$_@&@:e<@|^{=}{^j}?}1b}{,)}?}j

Online demo

This builds the possible paths by depth-first search, then uses a memoised function which counts the possible restricted forests for a given set of vertices. The function works recursively on the basis that any restricted forest for a given non-empty set of vertices consists of a path containing the smallest vertex and a restricted forest covering the vertices not in that path.


Auf dem Gittergraphen kann dies mit einer linearen Rekursion beschrieben werden, daher würde es mich nicht überraschen, herauszufinden, dass dies schön ist.
Peter Kagey

6

JavaScript (ES6),  160 158  146 Byte

n=>(g=(e,v,p)=>[...Array(N=2*n),N-1,1,n].reduce((s,x,i)=>(m=1<<(x=i<N?i:(p+x)%N))&v?s:s+g((i>=N)/p?[...e,1<<p|m]:e,v|m,x),g[e.sort()]^(g[e]=1)))``

Probieren Sie es online!

Anmerkungen:

  • Dies ist recht ineffizient und wird bei TIO eine Zeitüberschreitung verursachen n>4.
  • ein(5)=10204 wurde in etwas weniger als 3 Minuten auf meinem Laptop gefunden.

Kommentiert

n => (                        // n = input
  g = (                       // g = recursive function taking:
    e,                        //   e[] = array holding visited edges
    v,                        //   v   = bitmask holding visited vertices
    p                         //   p   = previous vertex
  ) =>                        // we iterate over an array of N + 3 entries, where N = 2n:
    [ ...Array(N = 2 * n),    //   - 0...N-1: each vertex of the N-gon (starting points)
      N - 1,                  //   - N      : previous vertex \
      1,                      //   - N+1    : next vertex      }-- connected to p
      n                       //   - N+2    : opposite vertex /
    ].reduce((s, x, i) =>     // reduce() loop with s = accumulator, x = vertex, i = index:
      ( m = 1 << (            //   m is a bitmask where only the x-th bit is set
          x = i < N           //   and x is either:
              ? i             //   - i if i < N
              : (p + x) % N   //   - or (p + x) mod N otherwise
      )) & v ?                //   if this vertex was already visited:
        s                     //     leave s unchanged
      :                       //   else:
        s +                   //     add to s
        g(                    //     the result of a recursive call:
          (i >= N) / p ?      //       if p and x are connected (i >= N and p is defined):
            [ ...e,           //         append to e[]:
              1 << p | m      //           the edge formed by p and x
            ]                 //           and uniquely identified by 1 << p | 1 << x
          :                   //       else:
            e,                //         leave e[] unchanged
          v | m,              //       mark the vertex x as visited
          x                   //       previous vertex = x
        ),                    //     end of recursive call
      g[e.sort()] ^           //   sort the edges and yield 1 if this list of edges has not
      (g[e] = 1)              //   already been encountered; either way, save it in g
    )                         // end of reduce()
)``                           // initial call to g with e = ['']

2

Jelly , 61-58 Bytes

®R,³;Ø+
Ḥ©Ḷµ1ị+¢%®ḟ€;€€1¦-Ẏ;€)Ẏ$ƬẎṣ€-Ẉ’ẠƊƇU¹Ø.ị>/Ɗ?€€Ṣ€QL‘

Probieren Sie es online!

Dies ist die kürzere Version; Es ist für eine kürzere Länge im Vergleich zur algorithmischen Komplexität und Geschwindigkeit optimiert.

Jelly , 85 Bytes

%®ḟ
1ị+³;Ø+¤ç,1ị+®_3¤R‘¤Ʋç;€-Ʋ“”2ị>-Ʋ?Ẏ;€
Ḥ©Ḷ;€-Ç€Ẏ$ƬẎṣ€-Ẉ=1ẸƊÐḟU¹1ị>0ị$Ʋ?€€Ṣ€QL‘+=2$

Probieren Sie es online!

Hier ist eine längere Version, die zusätzlichen Code hinzufügt, um zu vermeiden, dass redundante Pfade verwendet werden. Die Prüfung für n = 2 am Ende soll mit dem speziellen Fall für n = 2 fertig werden, der im Beispiel wie ein rotes / blaues Kreuz aussieht und von diesem Code nicht generiert wird. Diese zweite Version hat n = 4 in weniger als 13 Sekunden auf TIO abgeschlossen, läuft aber bei höheren Zahlen ab.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.