Längste Dominokette

31

Herausforderungsbeschreibung

Dominoes ist ein Spiel, bei dem Kacheln mit zwei Werten gespielt werden - einer auf der linken Seite, einer auf der rechten Seite, zum Beispiel [2|4]oder [4|5]. Zwei Kacheln können zusammengefügt werden, wenn sie einen gemeinsamen Wert enthalten. Die beiden obigen Kacheln können wie folgt verbunden werden:

[2|4][4|5]

Wir bezeichnen eine Folge nverbundener Kacheln als Kette der Länge n. Natürlich können Kacheln gedreht, also Kacheln [1|2], [1|3]und [5|3]zu einer Kette [2|1][1|3][3|5]der Länge 3 umgeordnet werden .

Bestimmen Sie anhand einer Liste von Ganzzahlpaaren die Länge der längsten Kette, die mit diesen Kacheln gebildet werden kann. Wenn die Liste leer ist, lautet die richtige Antwort 0(beachten Sie, dass Sie 1aus einer nicht leeren Liste von Kacheln immer eine Längenkette bilden können ).

Sample Input / Output

[(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)
shooqie
quelle
Irgendwelche Einschränkungen in Bezug auf Laufzeit oder Speicher? Denken Sie brachial alle Permutationen
Luis Mendo
3
@ LuisMendo: Ich bin mir ziemlich sicher, dass es sich bei diesem Problem um NP handelt, also O(n!)
feuere an,
I guess it's P
14.

Antworten:

5

Brachylog , 23 Bytes

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

Probieren Sie es online!

Erläuterung

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.

Mit anderen Worten, für Eingaben wie [[1:2]:[1:3]:[5:3]]versuchen wir, es in eine gültige Kette [[2:1]:[1:3]:[3:5]]umzuordnen und dann zu produzieren [1:1:3:3:5:_](wobei _ein Unbekannter dargestellt wird). Durch die Kombination ~cund :{…l2}aeffektive Aufteilung in Gruppen von 2 Elementen wird sichergestellt, dass alle Gruppen gleich sind. Wenn wir die Länge reduzieren (verdoppeln), ein Element vom Anfang entfernen und eines am Ende hinzufügen (keine Änderung) und in Paare gruppieren (die Länge halbieren), hat dies die gleiche Länge wie die ursprüngliche Dominokette.

Die „enthauptet“ Anweisung wird scheitern , wenn es keine Dominosteine im Eingang sind (eigentlich IIRC die :paauch fehlschlagen, aAbneigungen leere Listen), so dass wir einen Sonderfall für 0. (Ein wichtigen Grund brauchen wir haben die Asymmetrie zwischen bund ~kso ist dass wir für 1.) auch keinen Sonderfall brauchen


quelle
1
Meine
4

Brachylog , 29 Bytes

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

Probieren Sie es online!

Ich bin mir ziemlich sicher, dass das furchtbar lang ist, aber was auch immer. Das ist auch furchtbar langsam.

Erläuterung

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)

Der Grund, warum dies die größte findet, liegt darin, dass s - subsetAuswahlpunkte von der größten bis zur kleinsten Teilmenge generiert werden.

Tödlich
quelle
4

Mathematica, 191 Bytes

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

Kann ein gutes Stück Golf spielen, da bin ich mir sicher. Aber im Grunde derselbe Algorithmus wie in Fatalizes Brachylog-Antwort , mit einem etwas anderen Test am Ende.

Greg Martin
quelle
-1 Byte Differences/@Rest@Flatten@#~Partition~2Differences/@Partition[Rest@Flatten@#,2]InfixMap
:,
2

JavaScript (Firefox 30-57), 92 Byte

(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)))
  • list der letzte Wert oder undefinedfür den ersten Aufruf. l-nist daher ein falscher Wert, wenn das Domino gespielt werden kann.
  • d ist der zu betrachtende Domino.
  • nist das Ende des Dominos, das für die Verkettung mit dem vorherigen Domino in Betracht gezogen wird. Das andere Ende kann leicht berechnet werden als d[0]+d[1]-n.
  • 0, behandelt einfach den Basisfall ohne spielbare Dominosteine.
Neil
quelle
2

Haskell , 180 134 131 117 Bytes

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

Probieren Sie es online! Der neue Ansatz erwies sich als kürzer und effizienter. Anstelle aller möglichen Permutationen werden nur alle gültigen Ketten erstellt.

Bearbeiten: Die 117-Byte-Version ist wieder viel langsamer, aber immer noch schneller als die Brute-Force.


Alte Brute-Force-Methode:

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

Dies ist eine Brute-Force-Implementierung, bei der alle möglichen Permutationen ausprobiert werden (Die Anzahl der möglichen Permutationen scheint in A000165 , der " doppelten Fakultät von geraden Zahlen ", angegeben zu sein). Online ausprobieren verwaltet kaum Eingaben bis zu einer Länge von 7 (was beeindruckend ist, da 7 645120 Permutationen entspricht).

Verwendung:

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

Python 2, 279 Bytes

Golf gespielt:

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

Probieren Sie es online!

Gleiches mit einigen Kommentaren:

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

Ich poste, weil ich keine Python-Antworten gesehen habe ... jemand wird meine Antwort sehen und, angewidert, gezwungen sein, etwas viel Kürzeres und Effizienteres zu posten.

Bobas_Pett
quelle
0

Clojure, 198 183 Bytes

Update: Besserer Umgang mit "Maximum an möglicherweise leerer Sequenz"

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

Frühere Version:

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

Aufruf von Konventionen und Testfällen:

(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]])

Fgibt Elemente der Liste Cohne das Element zurück a, Mgibt die maximale Anzahl von Eingaben ingerers oder 1 zurück.

List die Hauptfunktion, wenn sie mit einem einzigen Argument aufgerufen wird, werden alle möglichen Startstücke generiert und die maximale Länge für jedes von ihnen ermittelt. Bei einem Aufruf mit zwei Argumenten list das das erste Element der Sequenz, zu dem das nächste Stück passen muss, und der RRest der Stücke.

Das Generieren von Permutationen und das "Auswählen eines Elements und Aufteilen zum Ausruhen" war recht schwierig, um es kurz und bündig umzusetzen.

NikoNyrh
quelle