Catena domino più lunga


31

Descrizione della sfida

Domino è un gioco giocato con tessere con due valori su di esso - uno a sinistra, uno a destra, per esempio [2|4]o [4|5]. È possibile unire due tessere se contengono un valore comune. Le due tessere sopra possono essere unite in questo modo:

[2|4][4|5]

Chiameremo una sequenza di ntessere unite una catena di lunghezza n. Naturalmente, le piastrelle possono essere ruotati, così piastrelle [1|2], [1|3]e [5|3]possono essere riorganizzate in una catena [2|1][1|3][3|5]di lunghezza 3.

Dato un elenco di coppie di numeri interi, determinare la lunghezza della catena più lunga che può essere formata usando queste tessere. Se l'elenco è vuoto, la risposta corretta è 0(nota che puoi sempre formare una catena di lunghezza 1da un elenco di tessere non vuoto).

Ingresso / uscita campione

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

Eventuali restrizioni sul tempo di esecuzione o sulla memoria? Pensa a forzare brutalmente tutte le permutazioni
Luis Mendo il

3
@LuisMendo: Abbastanza sicuro che questo problema sia NP, quindi O(n!)
accendi il

I guess it's P
l4m2

Risposte:


5

Brachylog , 23 byte

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

Provalo online!

Spiegazione

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.

Quindi, in altre parole, per input come [[1:2]:[1:3]:[5:3]], proviamo a riorganizzarlo in una catena valida [[2:1]:[1:3]:[3:5]], quindi appiattire / decapitare / unkknife per produrre [1:1:3:3:5:_](dove _rappresenta uno sconosciuto). La combinazione ~ce la :{…l2}asuddivide efficacemente in gruppi di 2 elementi e garantiamo che tutti i gruppi siano uguali. Quando abbiamo appiattito (raddoppiando la lunghezza), rimosso un elemento dall'inizio e aggiunto uno alla fine (nessuna modifica) e raggruppato in coppie (dimezzandone la lunghezza), questo avrà la stessa lunghezza della catena originale di domino.

L'istruzione "behead" fallirà se non ci sono domino nell'input (in realtà, anche IIRC :pafallirà; anon ci piacciono le liste vuote), quindi abbiamo bisogno di un caso speciale per 0. (Una grande ragione per cui abbiamo l'asimmetria tra bed ~kè così che non abbiamo bisogno anche di un caso speciale per 1.)


1
Bontà che è molto più breve ...
Fatalizza il

4

Brachylog , 29 byte

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

Provalo online!

Abbastanza sicuro che questo è terribilmente lungo, ma qualunque cosa. Anche questo è terribilmente lento.

Spiegazione

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)

Il motivo per cui questo troverà il più grande è perché s - subsetgenera punti di scelta dal sottoinsieme più grande a quello più piccolo.


4

Mathematica, 191 byte

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

Si può giocare a golf un bel po ', ne sono sicuro. Ma sostanzialmente lo stesso algoritmo della risposta Brachylog di Fatalize , con un test leggermente diverso alla fine.


-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)))
  • lè l'ultimo valore o undefinedper l'invocazione iniziale. l-nè quindi un valore falso se il domino può essere giocato.
  • d è il domino in esame.
  • nè la fine del domino in esame per il concatenamento al domino precedente. L'altra estremità può essere facilmente calcolata come d[0]+d[1]-n.
  • 0, gestisce semplicemente il case base senza domino giocabili.

2

Haskell , 180 134 131 117 byte

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

Provalo online! Il nuovo approccio si è rivelato sia più breve che più efficiente. Invece di tutte le possibili permutazioni vengono costruite solo tutte le catene valide.

Modifica: la versione da 117 byte è di nuovo molto più lenta, ma comunque più veloce della forza bruta.


Vecchio metodo della forza bruta:

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

Questa è un'implementazione a forza bruta che prova tutte le possibili permutazioni (il numero di possibili permutazioni sembra essere dato da A000165 , il " doppio fattoriale dei numeri pari "). Provalo online a malapena gestisce gli input fino alla lunghezza 7 (che è piuttosto impressionante in quanto 7 corrisponde a 645120 permutazioni).

Uso:

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

1

Python 2, 279 byte

golfed:

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

Provalo online!

Stessa cosa con alcuni commenti:

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

Sto postando perché non ho visto alcuna risposta Python ... qualcuno vedrà la mia risposta e, disgustato, sarà costretto a pubblicare qualcosa di molto più breve ed efficiente.


0

Clojure, 198 183 byte

Aggiornamento: migliore gestione del "massimo della sequenza possibilmente vuota"

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

Versione precedente:

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

Convocazione di convenzioni e casi di test:

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

Frestituisce elementi dell'elenco Csenza l'elemento a, Mrestituisce il massimo di ingerers di input o 1.

Lè la funzione principale, quando chiamata con un singolo argomento genera tutti i possibili pezzi di partenza e trova la lunghezza massima per ciascuno di essi. Se chiamato con due argomenti, lè il primo elemento della sequenza a cui il pezzo successivo deve corrispondere ed Rè il resto dei pezzi.

Generare permutazioni e "scegliere un elemento e dividerlo per riposare" è stato piuttosto difficile da implementare in modo succinto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.