Contando el número de bosques restringidos en la escala de longitud de Möbius n


13

La secuencia OEIS A020872 cuenta el número de bosques restringidos en la escalera Möbius M n .

El reto

El desafío es escribir un programa que tome un número entero como entrada n > 1y devuelva A020872(n), el número de bosques restringidos en la escalera Möbius M n . Este es el , por lo que gana el código más corto. (Un motivo ulterior es tal vez extender un poco la longitud de esta secuencia).

Definiciones

Un bosque restringido es una partición del gráfico de manera que cada parte es una ruta (no dirigida) o un vértice aislado.

La escalera de Möbius M n es un gráfico que puede pensarse en el 2n-gon con diagonales dibujadas entre todos los vértices opuestos.

Ejemplo

Aquí están los 34 bosques restringidos en M 2 (un cuadrado con diagonales dibujadas). Observe que el primer gráfico está dividido en cuatro vértices aislados, el segundo está dividido en una ruta y dos vértices aislados, etc. A020872 (2)


1
Los casos de prueba de 2 a 12: 34, 241, 1582, 10204, 65197, 415076, 2638366, 16759249, 106427154, 675771276, 4290678337. No estoy seguro de por qué 1no se requiere entrada, con salida 2.
Peter Taylor

@ PeterTaylor, ¡Gracias por agregar esos términos a OEIS! 1Excluí la entrada porque M_1 no está claramente definido en el artículo de Wikipedia. (En particular, tiene múltiples aristas o no es un gráfico cúbico.)
Peter Kagey

1
En realidad, esto suena como un buen candidato para una fastest-codeo fastest-algorithmdesafío.
mypetlion

1
Otros casos de prueba ( código de generación ): 13 a 17 son27242281044, 172964658642, 1098170541121, 6972388689086, 44268329738124
Peter Taylor

1
Bien, creo que tu motivo oculto está más que satisfecho.
Peter Taylor

Respuestas:


10

CJam ( 58 56 caracteres)

Algunos caracteres no pueden imprimirse, y uno es una pestaña que el software de StackExchange eliminará:

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

Demo en línea . Esto se ejecutará en línea durante n = 400 en aproximadamente tres segundos.

Codificado por 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=

Explicación

Una escalera de Möbius es básicamente una escalera con dos bordes adicionales. Dado un bosque restringido en una escalera, se puede levantar entre 1 y 4 bosques restringidos en la escalera de Möbius. Se pueden agregar los bordes siempre que no cree un vértice de grado 3 o un ciclo. Los grados de las cuatro esquinas y sus interconexiones forman 116 clases de bosque restringido en la escalera, aunque algunos de ellos son equivalentes debido a las simetrías del rectángulo. Escribí un programa para analizar las extensiones de una escalera de longitud n a una de longitud n + 1, y luego fusioné las clases en 26 clases de equivalencia. Esto da una forma cerrada

[1111]T[1220 01211234 410 00 010 0]norte-2[0 010 00 0]+

[221111122]T[21111111110 010 00 010 010 00 00 020 010 00 00 00 00 00 010 010 00 00 00 00 00 00 010 00 00 00 01110 00 00 00 00 0110 00 010 00 00 00 01132211214 420 00 00 010 00 00 00 02]norte-2[0 00 0220 00 00 00 00 0]+

[124 44 411322234 44 4]T[0 00 00 010 00 00 00 00 00 010 00 00 020 00 010 00 00 00 00 00 00 00 00 0120 0110 0110 011110 00 04 40 00 030 00 020 00 00 00 00 00 00 00 00 00 00 010 0210 00 010 00 00 00 00 00 00 00 00 01110 00 010 00 020 00 010 00 00 00 0120 00 00 00 010 00 00 0120 010 00 010 00 00 00 00 00 00 00 00 00 00 020 00 020 00 010 00 00 00 00 00 00 00 00 00 00 00 00 010 00 00 00 00 00 00 00 00 00 010 0220 00 0230 0110 0210 0124 4]norte-2[10 01120 010 00 00 0121]

así que los valores se pueden calcular rápidamente tomando tres recurrencias lineales y luego agregándolas, pero esto no parece muy complejo.

Sin embargo, si tomamos los factores irreducibles de los diversos polinomios característicos y multiplicamos juntos uno de cada uno (ignorando la multiplicidad) obtenemos un polinomio de grado 10 que da una recurrencia lineal única que funciona.

Enfoque constructivo (58 caracteres)

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

Demo en línea . Se ejecutará en línea n=2sin problemas y n=3con un poco de paciencia. Porque n=1se bloquea, pero dado que OP ha elegido excluir ese caso de los requisitos, no es un problema fundamental.

Disección

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

Una versión más eficiente toma 98 bytes:

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

Demostración en línea

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.


En el gráfico de cuadrícula, esto se puede describir con una recursión lineal, por lo que no me sorprendería descubrir que esto es bueno.
Peter Kagey

6

JavaScript (ES6),  160 158  146 bytes

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

Pruébalo en línea!

Notas:

  • Esto es bastante ineficiente y se agotará el tiempo de espera en TIO para norte>4 4.
  • un(5 5)=10204 fue encontrado en un poco menos de 3 minutos en mi computadora portátil.

Comentado

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

Jalea , 61 58 bytes

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

Pruébalo en línea!

Esta es la versión más corta; Está optimizado para una longitud más corta versus complejidad algorítmica y velocidad.

Jalea , 85 bytes

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

Pruébalo en línea!

Aquí hay una versión más larga que agrega código adicional para evitar probar rutas redundantes. La comprobación de n = 2 al final es para hacer frente al caso específico de n = 2 que se ve como una cruz roja / azul en el ejemplo y no es generado por este código. Esta segunda versión completó n = 4 en menos de 13 segundos en TIO, pero agota el tiempo para números más altos.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.