最长的多米诺骨牌链


31

挑战说明

多米诺骨牌(Dominos)是一款带有两个值的图块-左边是一个值,右边是一个值,例如[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)

运行时间或内存有限制吗?想一下所有设置都采用蛮横方式
Luis Mendo

3
@LuisMendo:可以肯定的是这个问题是NP,所以O(n!)请随心所欲
shooqie

I guess it's P
l4m2

Answers:


5

Brachylog,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有效地将其分为2个元素的组,我们确保所有组均相等。当我们展平(将长度加倍),从开头删除一个元素并在末尾添加一个元素(不变)并成对分组(将长度减半)时,它的长度将与原始多米诺骨牌链的长度相同。

如果输入中没有多米诺骨牌,“ behead”指令将失败(实际上,IIRC :pa也会失败;a不喜欢空列表),因此我们需要将0 设为特例。(一个大原因是,band 之间存在不对称性~k我们也不需要1的特殊情况)


1
天哪

4

Brachylog,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

Mathematica,191个字节

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

我敢肯定,可以打高尔夫。但是与Fatalize的Brachylog答案中的算法基本相同,但最后的测试略有不同。


-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

我发布是因为我没有看到任何python答案...有人会看到我的答案,并且厌恶地被迫发布更短,更有效的内容。


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返回list C的元素a,不包含element ,M返回输入指针的最大值或1。

L是主要功能,当使用单个参数调用时,它会生成所有可能的起始片段并找到每个起始片段的最大长度。当使用两个参数调用时l,它是下一部分必须与之匹配的序列的第一个元素,并且R是其余部分。

生成置换和“选择一个元素并拆分为其余部分”是很难实现的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.