Підрахунок кількості лісів з обмеженими можливостями на сходах Мебіуса довжиною n


13

Послідовність OEIS A020872 підраховує кількість лісів з обмеженими можливостями на сходах Möbius M n .

Змагання

Завдання полягає в тому, щоб написати програму, яка приймає ціле число як вхід n > 1і повертає A020872(n)кількість лісів з обмеженням на сходах Мебіуса M n . Це , тому найкоротший код виграє. (Останнім мотивом є, можливо, трохи збільшити довжину цієї послідовності.)

Визначення

Обмежений ліс є розбиттям графа таким чином, що кожна частина є або (неорієнтованим) шляхом або ізольована вершина.

Мёбіусово сходи М п являє собою графік , який можна розглядати в 2n-кутник з діагоналями намальованих між усіма протилежними вершинами.

Приклад

Ось 34 ліси з обмеженим доступом на M 2 (квадрат з нанесеними діагоналями). Зауважте, що перший графік розділений на чотири ізольованих вершини, другий розділений на один шлях та дві ізольовані вершини тощо. A020872 (2)


1
Тестові випадки від 2 до 12: 34, 241, 1582, 10204, 65197, 415076, 2638366, 16759249, 106427154, 675771276, 4290678337. Я не впевнений, чому введення даних 1також не потрібно з результатом 2.
Пітер Тейлор

@PeterTaylor, Дякую за додавання цих термінів до OEIS! Я виключив дані, 1оскільки M_1 чітко не визначений у статті Вікіпедії. (Зокрема, у нього є кілька країв, або це не кубічний графік.)
Пітер Кагей,

1
Це насправді звучить як хороший кандидат для fastest-codeчи fastest-algorithmвиклику.
mypetlion

1
Подальші тестові справи ( код покоління ): 13-1727242281044, 172964658642, 1098170541121, 6972388689086, 44268329738124
Пітер Тейлор

1
Правильно, я думаю, що ваш останній мотив більш ніж задоволений.
Пітер Тейлор

Відповіді:


10

CJam ( 58 56 символів)

Деякі символи не друкуються, а один - це вкладка, яку буде керовано програмним забезпеченням StackExchange:

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

Інтернет демо . Це буде тривати в Інтернеті протягом n = 400 приблизно за три секунди.

Зашифровано 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=

Пояснення

Сходи Möbius - це в основному драбина з двома додатковими кромками. Враховуючи обмежений ліс на сходах, його можна підняти на 1–4 ліси з обмеженим доступом на сходах Мебіуса. Краї можна додати за умови, що не створюється вершина ступеня 3 або циклу. Ступені чотирьох кутів та їх взаємозв'язок утворюють 116 класів лісу з обмеженими можливостями на сходах, хоча деякі з них рівноцінні через симетрії прямокутника. Я написав програму для аналізу розширень сходів довжиною n до однієї довжини n + 1, а потім об'єднав класи в 26 класів еквівалентності. Це дає закриту форму

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

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

[1244113222344]T[0001000000100020010000000001201101101111004003002000000000001021001000000000111001002001000012000010001201001000000000002002001000000000000010000000000102200230110210124]n2[1011201000121]

тому значення можна швидко обчислити, взявши три лінійні повторення, а потім додавши їх, але це не дуже вибагливо.

Однак якщо взяти невідводячі множники різних характерних многочленів і множимо разом один з кожного (ігноруючи кратність), ми отримаємо многочлен ступеня 10, який дає робочий єдиний лінійний повтор.

Конструктивний підхід (58 символів)

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

Інтернет демо . Він працюватиме в Інтернеті n=2без проблем і n=3з трохи терпіння. Адже n=1це збій, але оскільки ОП вирішила виключити цю справу з вимог, це не є принциповою проблемою.

Розсічення

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

Більш ефективна версія займає 98 байт:

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

Демонстрація в Інтернеті

Це будує можливі шляхи шляхом першого глибинного пошуку, а потім використовує функцію запам'ятовування, яка підраховує можливі ліси з обмеженням для заданого набору вершин. Функція працює рекурсивно, виходячи з того, що будь-який обмежений ліс для заданого непустого набору вершин складається з шляху, що містить найменшу вершину, і лісу з обмеженими можливостями, що охоплює вершини, які не знаходяться на цьому шляху.


На сітчастому графіку це можна описати лінійною рекурсією, тому мене не здивує, дізнавшись, що це добре.
Пітер Кагей

6

JavaScript (ES6),  160 158  146 байт

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

Спробуйте в Інтернеті!

Примітки:

  • n>4
  • a(5)=10204

Прокоментував

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

Желе , 61 58 байт

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

Спробуйте в Інтернеті!

Це коротша версія; він оптимізований для меншої довжини проти алгоритмічної складності та швидкості.

Желе , 85 байт

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

Спробуйте в Інтернеті!

Ось довша версія, яка додає додатковий код, щоб уникнути спроб зайвих шляхів. Перевірка на n = 2 в кінці полягає в тому, щоб впоратись із конкретним випадком для n = 2, який схожий на червоний / синій хрест у прикладі та не генерується цим кодом. Ця друга версія завершила n = 4 менш ніж за 13 секунд на TIO, але час очікується на більші числа.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.