Найдовша мережа доміно


31

Опис виклику

Доміно - це гра, яку грають плитки з двома значеннями на ній - одне зліва, одне праворуч, наприклад [2|4]або [4|5]. Дві плитки можна з'єднати разом, якщо вони містять загальне значення. Дві плитки вище можна з'єднати так:

[2|4][4|5]

Ми будемо називати послідовність nз'єднаних плиток ланцюжком довжиною n. Звичайно, плитки можна повертати, так що плитки [1|2], [1|3]і [5|3]можуть бути змінені в ланцюжок [2|1][1|3][3|5]довжиною 3.

Давши список пар цілих чисел, визначте довжину найдовшої ланцюга, яку можна сформувати за допомогою цих плиток. Якщо список порожній, правильна відповідь 0(зауважте, що завжди можна сформувати ланцюжок довжини 1з не порожнього списку плиток).

Зразок вводу / виводу

[(0, -1), (1, -1), (0, 3), (3, 0), (3, 1), (-2, -1), (0, -1), (2, -2), (-1, 2), (3, -3)] -> 10
([-1|0][0|-1][-1|2][2|-2][-2|-1][-1|1][1|3][3|0][0|3][3|-3])

[(17, -7), (4, -9), (12, -3), (-17, -17), (14, -10), (-6, 17), (-16, 5), (-3, -16), (-16, 19), (12, -8)] -> 4
([5|-16][-16|-3][-3|12][12|-8])

[(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)] -> 7
([1|1][1|1][1|1][1|1][1|1][1|1][1|1])

[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10, 11)] -> 1
(any chain of length 1)

[] -> 0
(no chain can be formed)

Будь-які обмеження часу роботи чи пам’яті? Подумайте, що переслідують усі перестановки
Луїс Мендо

3
@LuisMendo: Досить впевнений, що ця проблема є NP, тож O(n!)
розпалюй

I guess it's P
l4m2

Відповіді:


5

Брахілог , 23 байти

s:papcb~k~c:{#=l2}al|,0

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

Пояснення

s:papcb~k~c:{#=l2}al|,0
s                         Check subsets of the input (longest first).
 :pa                      Check all permutations inside the input's elements
    p                     and all permutations /of/ the input's elements.
     c                    Flatten the result;
      b                   delete the first element;
       ~k                 find something that can be appended to the end so that
         ~c               the result can be unflattened into
           :{    }a       a list whose elements each have the property:
             #=             all the elements are equal
               l2           and the list has two elements.
                   l      If you can, return that list's length.
                    |,0   If all else fails, return 0.

Отже, іншими словами, для введення, як [[1:2]:[1:3]:[5:3]]ми, ми намагаємось переставити його у дійсний ланцюг [[2:1]:[1:3]:[3:5]], а потім вирівняти / обезголовити / зняти ножем для отримання [1:1:3:3:5:_](де _є невідомим). Поєднання ~cта :{…l2}aефективно розбиває це на групи з двох елементів, і ми гарантуємо, що всі групи рівні. Коли ми розрівняли (подвоєння довжини), видалили один елемент із початку та додали один на кінці (без змін) та згрупувались у пари (вдвічі зменшити довжину), це матиме таку ж довжину, що й початковий ланцюжок доміно.

Інструкція "обезголовлення" вийде з ладу, якщо у вході немає доміно (насправді, IIRC :paтакож не вдасться; не aлюбить порожні списки), тому нам потрібен спеціальний випадок для 0. (Однією з великих причин у нас є асиметрія між bі ~kтак що нам також не потрібен спеціальний випадок для 1.)


1
Добре, що настільки коротше ...
Фаталізувати

4

Брахілог , 29 байт

v0|sp:{|r}aLcbk@b:{l:2%0}a,Ll

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

Досить впевнений, що це жахливо довго, але що б там не було. Це також жахливо повільно.

Пояснення

v0                               Input = [], Output = 0
  |                              Or
   sp:{|r}aL                     L (a correct chain) must be a permutation of a subset of the
                                   Input with each tile being left as-is or reversed
           Lcbk                  Concatenate L into a single list and remove the first and
                                   last elements (the two end values don't matter)
               @b                Create a list of sublists which when concatenated results in
                                   L, and where each sublist's elements are identical
                 :{     }a,      Apply this to each sublist:
                   l:2%0           It has even length
                           Ll    Output = length(L)

Причина цього виявиться найбільшою, тому що s - subsetгенерує пункти вибору від найбільшого до найменшого підмножини.


4

Математика, 191 байт

If[#=={},0,Max[Length/@Select[Flatten[Rest@Permutations[#,∞]&/@Flatten[#,Depth[#]-4]&@Outer[List,##,1]&@@({#,Reverse@#}&/@#),1],MatchQ[Differences/@Partition[Rest@Flatten@#,2],{{0}...}]&]]]&

Можливо, я дуже впевнений, що можна пограти в гольф. Але в основному той же алгоритм, що і у відповіді Брахілога Фаталізе , з кінцем іншим тестом в кінці.


-1 байт: Differences/@Rest@Flatten@#~Partition~2замість Differences/@Partition[Rest@Flatten@#,2]( Infixмає вищий пріоритет Map)
JungHwan Min

2

JavaScript (Firefox 30-57), 92 байти

(a,l)=>Math.max(0,...(for(d of a)for(n of d)if(!(l-n))1+f(a.filter(e=>e!=d),d[0]+d[1]-n)))
  • l- це останнє значення або undefinedдля початкового виклику. l-nТаким чином, це помилкова цінність, якщо в доміно можна грати.
  • d - доміно, що розглядається.
  • n- це кінець розглянутого доміно для прив'язування до попереднього доміно. Інший кінець може бути легко обчислений як d[0]+d[1]-n.
  • 0, просто обробляє базовий корпус не відтворюваних доміно.

2

Haskell , 180 134 131 117 байт

p d=maximum$0:(f[]0d=<<d)
f u n[]c=[n]
f u n(e@(c,d):r)a@(_,b)=f(e:u)n r a++(f[](n+1)(r++u)=<<[e|b==c]++[(d,c)|b==d])

Спробуйте в Інтернеті! Новий підхід виявився і коротшим, і більш ефективним. Замість усіх можливих перестановок будуються лише всі дійсні ланцюги.

Редагувати: версія 117 байт знову набагато повільніше, але все ж швидша за грубу силу.


Старий метод жорстокої сили:

p(t@(a,b):r)=[i[]t,i[](b,a)]>>=(=<<p r)
p e=[e]
i h x[]=[h++[x]]
i h x(y:t)=(h++x:y:t):i(h++[y])x t
c%[]=[0]
c%((_,a):r@((b,_):_))|a/=b=1%r|c<-c+1=c:c%r
c%e=[c]
maximum.(>>=(1%)).p

Це реалізація грубої сили, яка намагається здійснити всі можливі перестановки (здається, що кількість можливих перестановок надається A000165 , " подвійним факторієм парних чисел "). Спробуйте в режимі он-лайн ледве керування введеннями довжиною до 7 (що начебто вражає, оскільки 7 відповідає перестановкам 645120 ).

Використання:

Prelude> maximum.(>>=(1%)).p $ [(1,2),(3,2),(4,5),(6,7),(5,5),(4,2),(0,0)]
4

1

Python 2, 279 байт

Гольф:

l=input()
m=0
def f(a,b):
 global m
 l=len(b)
 if l>m:m=l
 for i in a:
  k=a.index(i)
  d=a[:k]+a[k+1:]
  e=[i[::-1]]
  if not b:f(d,[i])
  elif i[0]==b[-1][1]:f(d,b+[i])
  elif i[0]==b[0][0]:f(d,e+b)
  elif i[1]==b[0][0]:f(d,[i]+b)
  elif i[1]==b[-1][1]:f(d,b+e)
f(l,[])
print m

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

Те ж саме з деякими коментарями:

l=input()
m=0
def f(a,b):
 global m
 l=len(b)
 if l>m:m=l                      # if there is a larger chain
 for i in a:
  k=a.index(i)
  d=a[:k]+a[k+1:]                # list excluding i
  e=[i[::-1]]                    # reverse i
  if not b:f(d,[i])              # if b is empty
                                 # ways the domino can be placed:
  elif i[0]==b[-1][1]:f(d,b+[i]) # left side on the right
  elif i[0]==b[0][0]:f(d,e+b)    # (reversed) left side on the left
  elif i[1]==b[0][0]:f(d,[i]+b)  # right side on left
  elif i[1]==b[-1][1]:f(d,b+e)   # (reversed) right side on the right
f(l,[])
print m

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


0

Clojure, 198 183 байт

Оновлення: Краще обробляти "максимум можливо порожньої послідовності"

(defn F[a C](remove(fn[i](identical? i a))C))(defn M[C](apply max 0 C))(defn L([P](M(for[p P l p](L l(F p P)))))([l R](+(M(for[r R[i j][[0 1][1 0]]:when(=(r i)l)](L(r j)(F r R))))1)))

Більш рання версія:

(defn F[a C](remove(fn[i](identical? i a))C))(defn M[C](apply max 1 C))(defn L([P](if(empty? P)0(M(for[p P l p](L l(F p P))))))([l R](M(for[r R[i j][[0 1][1 0]]:when(=(r i)l)](+(L(r j)(F r R))1)))))

Виклик конвенції та тестових випадків:

(L [])
(L [[2 4] [3 2] [1 4]])
(L [[3, 1] [0, 3], [1, 1]])
(L [[17 -7] [4 -9] [12 -3] [-17 -17] [14 -10] [-6 17] [-16 5] [-3 -16] [-16 19] [12 -8]])
(L [[0 -1] [1 -1] [0 3] [3 0] [3 1] [-2 -1] [0 -1] [2 -2] [-1 2] [3 -3]])
(L [[1 1] [1 1] [1 1] [1 1] [1 1] [1 1] [1 1]])

Fповертає елементи списку Cбез елемента a, Mповертає макс вхідних ingerers або 1.

Lє основною функцією, коли викликається одним аргументом, він генерує всі можливі вихідні фрагменти і знаходить максимальну довжину для кожного з них. Коли викликається двома аргументами, lце перший елемент послідовності, якому повинен відповідати наступний фрагмент, і Rце решта частин.

Створення перестановок і "вибрати один елемент і розділитись на відпочинок" було досить складно реалізувати стисло.

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