Compter le nombre de forêts restreintes sur l'échelle de Möbius de longueur n


13

La séquence OEIS A020872 compte le nombre de forêts restreintes sur l' échelle de Möbius M n .

Le défi

Le défi consiste à écrire un programme qui prend un entier en entrée n > 1et renvoie A020872(n)le nombre de forêts restreintes sur l'échelle de Möbius M n . C'est du , donc le code le plus court l'emporte. (Un motif ultérieur est peut-être d'étendre un peu la longueur de cette séquence.)

Définitions

Une forêt restreinte est une partition du graphe telle que chaque partie est soit un chemin (non dirigé) soit un sommet isolé.

L' échelle Möbius M n est un graphique que l'on peut penser au 2n-gon avec des diagonales tracées entre tous les sommets opposés.

Exemple

Voici les 34 forêts restreintes sur M 2 (un carré avec des diagonales dessinées). Notez que le premier graphique est partitionné en quatre sommets isolés, le second est partitionné en un chemin et deux sommets isolés, etc. A020872 (2)


1
Les cas de test de 2 à 12: 34, 241, 1582, 10204, 65197, 415076, 2638366, 16759249, 106427154, 675771276, 4290678337. Je ne sais pas pourquoi l'entrée 1n'est pas également requise, avec la sortie 2.
Peter Taylor

@PeterTaylor, Merci d'avoir ajouté ces termes à OEIS! J'ai exclu les entrées 1car M_1 n'est pas clairement défini dans l'article Wikipedia. (En particulier, soit il a plusieurs arêtes, soit ce n'est pas un graphique cubique.)
Peter Kagey

1
Cela semble en fait comme un bon candidat pour un fastest-codeou fastest-algorithmdéfi.
mypetlion

1
D'autres cas de test ( code de génération ): 13 à 17 sont27242281044, 172964658642, 1098170541121, 6972388689086, 44268329738124
Peter Taylor

1
Bon, je pense que votre arrière-pensée est plus que satisfaite.
Peter Taylor

Réponses:


10

CJam ( 58 56 caractères)

Certains caractères non imprimables, et l'un est un onglet qui sera modifié par le logiciel StackExchange:

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

Démo en ligne . Cela s'exécutera en ligne pour n = 400 en environ trois secondes.

Encodé par 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=

Explication

Une échelle Möbius est essentiellement une échelle avec deux bords supplémentaires. Étant donné une forêt restreinte sur une échelle, elle peut être élevée entre 1 et 4 forêts restreintes sur l'échelle Möbius. Les bords peuvent être ajoutés à condition de ne pas créer de sommet de degré 3 ni de cycle. Les degrés des quatre coins et leurs interconnexions forment 116 classes de forêt restreinte sur l'échelle, bien que certains d'entre eux soient équivalents en raison des symétries du rectangle. J'ai écrit un programme pour analyser les extensions d'une échelle de longueur n à une longueur n + 1, puis j'ai fusionné les classes en 26 classes d'équivalence. Cela donne une forme fermée

[1111]T[1220121123410010]n-2[0100]+

[221111122]T[211111111101001010002010000001010000000100001110000011001000011322112142000100002]n-2[002200000]+

[1244113222344]T[0001000000100020010000000001201101101111004003002000000000001021001000000000111001002001000012000010001201001000000000002002001000000000000010000000000102200230110210124]n-2[1011201000121]

les valeurs peuvent donc être calculées rapidement en prenant trois récurrences linéaires puis en les ajoutant, mais cela n'a pas l'air très golfique.

Cependant, si nous prenons les facteurs irréductibles des divers polynômes caractéristiques et multiplions ensemble l'un de chacun (en ignorant la multiplicité), nous obtenons un polynôme de degré 10 qui donne une seule récurrence linéaire de travail.

Approche constructive (58 caractères)

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

Démo en ligne . Il fonctionnera en ligne n=2sans problème et n=3avec un peu de patience. Car n=1il se bloque, mais comme OP a choisi d'exclure ce cas des exigences, ce n'est pas un problème fondamental.

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

Une version plus efficace prend 98 octets:

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

Démo en ligne

Cela construit les chemins possibles par une recherche en profondeur d'abord, puis utilise une fonction mémorisée qui compte les forêts restreintes possibles pour un ensemble donné de sommets. La fonction fonctionne récursivement sur la base que toute forêt restreinte pour un ensemble de sommets non vide donné se compose d'un chemin contenant le plus petit sommet et d'une forêt restreinte couvrant les sommets ne se trouvant pas dans ce chemin.


Sur le graphique de la grille, cela peut être décrit avec une récursivité linéaire, donc cela ne me surprendrait pas de découvrir que c'est bien.
Peter Kagey

6

JavaScript (ES6),  160 158  146 octets

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

Essayez-le en ligne!

Remarques:

  • Ceci est assez inefficace et expirera sur TIO pendant n>4.
  • une(5)=10204 a été trouvé en un peu moins de 3 minutes sur mon ordinateur portable.

Commenté

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

Gelée , 61 58 octets

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

Essayez-le en ligne!

Ceci est la version courte; il est optimisé pour une longueur plus courte par rapport à la complexité et à la vitesse algorithmiques.

Gelée , 85 octets

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

Essayez-le en ligne!

Voici une version plus longue qui ajoute du code supplémentaire pour éviter d'essayer des chemins redondants. La vérification de n = 2 à la fin consiste à faire face au cas spécifique de n = 2 qui ressemble à une croix rouge / bleue dans l'exemple et n'est pas généré par ce code. Cette deuxième version a terminé n = 4 en moins de 13 secondes sur TIO, mais expire pour des nombres plus élevés.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.