Liczenie liczby lasów objętych ograniczeniami na drabinie Möbiusa o długości n


13

Sekwencja OEIS A020872 zlicza liczbę lasów objętych ograniczeniami na drabinie Möbiusa M n .

Wyzwanie

Wyzwanie polega na napisaniu programu, który przyjmuje liczbę całkowitą jako dane wejściowe n > 1i zwraca A020872(n), liczbę ograniczonych lasów na drabinie Möbiusa M n . To jest , więc wygrywa najkrótszy kod. (Ukrytym motywem jest być może nieco wydłużenie długości tej sekwencji).

Definicje

Ograniczony las jest podział na wykresie tak, że każda część jest albo (niekierowanego) ścieżki lub izolowany wierzchołek.

Möbiusa drabiny K n to wykres, który może być uważany 2n-gon przek łączącymi wszystkie wierzchołki przeciwległych.

Przykład

Oto 34 ograniczone lasy na M 2 (kwadrat z narysowanymi przekątnymi). Zauważ, że pierwszy wykres jest podzielony na cztery izolowane wierzchołki, drugi jest podzielony na jedną ścieżkę i dwa izolowane wierzchołki itp. A020872 (2)


1
Przypadków od 2 do 12 testów: 34, 241, 1582, 10204, 65197, 415076, 2638366, 16759249, 106427154, 675771276, 4290678337. Nie jestem pewien, dlaczego dane wejściowe 1nie są również wymagane w przypadku danych wyjściowych 2.
Peter Taylor

@PeterTaylor, Dziękujemy za dodanie tych warunków do OEIS! Wyłączyłem dane wejściowe, 1ponieważ M_1 nie jest jasno zdefiniowane w artykule w Wikipedii. (W szczególności albo ma wiele krawędzi, albo nie jest sześciennym wykresem).
Peter Kagey

1
To właściwie brzmi jak dobry kandydat na wyzwanie fastest-codelub fastest-algorithmwyzwanie.
mypetlion

1
Dalsze przypadki testowe ( kod generacyjny ): 13 do 17 to27242281044, 172964658642, 1098170541121, 6972388689086, 44268329738124
Peter Taylor

1
Racja, myślę, że twój ukryty motyw jest więcej niż zadowolony.
Peter Taylor

Odpowiedzi:


10

CJam ( 58 56 znaków)

Niektóre znaki są niedrukowalne, a jedna to zakładka, która zostanie zniekształcona przez oprogramowanie StackExchange:

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

Demo online . To będzie działać online przez n = 400 za około trzy sekundy.

Kodowane przez 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=

Wyjaśnienie

Drabina Möbius to w zasadzie drabina z dwoma dodatkowymi krawędziami. Biorąc pod uwagę ograniczony las na drabinie, można go podnieść do 1–4 ograniczonych lasów na drabinie Möbius. Krawędzie można dodawać, pod warunkiem, że nie tworzy wierzchołka stopnia 3 ani cyklu. Stopnie czterech rogów i ich wzajemne połączenia tworzą 116 klas ograniczonego lasu na drabinie, chociaż niektóre z nich są równoważne ze względu na symetrie prostokąta. Napisałem program do analizy rozszerzeń drabiny o długości n do jednej o długości n + 1, a następnie połączyłem klasy w 26 klas równoważności. To daje zamknięty formularz

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

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

[1244113222344]T[0001000000100020010000000001201101101111004003002000000000001021001000000000111001002001000012000010001201001000000000002002001000000000000010000000000102200230110210124]n2[1011201000121]

więc wartości można szybko obliczyć, biorąc trzy liniowe rekurencje, a następnie dodając je, ale to nie wygląda bardzo golfowo.

Jeśli jednak weźmiemy pod uwagę czynniki nieredukowalne różnych charakterystycznych wielomianów i pomnożymy jeden z nich (ignorując wielokrotność), otrzymamy wielomian stopnia 10, który daje działającą pojedynczą rekurencję liniową.

Konstruktywne podejście (58 znaków)

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

Demo online . Będzie działał online n=2bez problemów i n=3przy odrobinie cierpliwości. Ponieważ n=1ulega awarii, ale ponieważ OP zdecydowało się wykluczyć tę sprawę z wymagań, nie jest to podstawowy problem.

Sekcja

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

Bardziej wydajna wersja zajmuje 98 bajtów:

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

Demo online

To buduje możliwe ścieżki przez wyszukiwanie od głębokości, a następnie używa zapamiętanej funkcji, która zlicza możliwe ograniczone lasy dla danego zestawu wierzchołków. Funkcja działa rekurencyjnie na podstawie tego, że każdy ograniczony las dla danego niepustego zestawu wierzchołków składa się ze ścieżki zawierającej najmniejszy wierzchołek i ograniczony las obejmujący wierzchołki nie znajdujące się na tej ścieżce.


Na wykresie siatki można to opisać za pomocą rekurencji liniowej, więc nie zaskoczyłoby mnie stwierdzenie, że jest to miłe.
Peter Kagey

6

JavaScript (ES6),  160 158  146 bajtów

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

Wypróbuj online!

Uwagi:

  • Jest to dość nieefektywne i spowoduje przekroczenie limitu czasu dla TIO dla .n>4
  • a(5)=10204 znaleziono na trochę mniej niż 3 minuty na moim laptopie.

Skomentował

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

Galaretka , 61 58 bajtów

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

Wypróbuj online!

To jest krótsza wersja; jest zoptymalizowany pod kątem krótszej długości w porównaniu do złożoności algorytmicznej i szybkości.

Galaretka , 85 bajtów

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

Wypróbuj online!

Oto dłuższa wersja, która dodaje dodatkowy kod, aby uniknąć wypróbowywania zbędnych ścieżek. Sprawdzanie, czy n = 2 na końcu ma poradzić sobie ze szczególnym przypadkiem dla n = 2, który wygląda jak czerwony / niebieski krzyż w przykładzie i nie jest generowany przez ten kod. Ta druga wersja zakończyła n = 4 w TIO w czasie krótszym niż 13 sekund, ale przekroczono limit czasu dla wyższych liczb.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.