Gioca a Rummikub!


11

Nota: ciò è correlato a una variante del gioco Rummikub


Contesto e regole

Rummikub è un gioco basato su tessere. Esistono quattro colori: rosso, arancione, blu e nero. Per ogni colore ci sono 13 tessere (etichettate da 1 a 13) e ci sono anche 2 jolly che sono indipendenti dal colore, quindi ci sono 54 pezzi in totale. In questa variante di Rummikub, ogni giocatore riceve 14 tessere e deve ottenere un'altra tessera e rilasciarne un'altra ogni round, in modo che il conteggio delle tessere sia costante. I giocatori non vedono le rispettive tessere. L'obiettivo è quello di raggruppare le tessere, in modo tale che tutti i pezzi appartengano ad almeno un gruppo (vedi sotto). Quando un giocatore ha raggruppato tutti i pezzi, lascia cadere il tabellone delle tessere e rivela i propri pezzi. Gli altri controllano quindi se tutte le combinazioni sono valide e se lo sono, il giocatore vince il round.

Come possono essere raggruppate le tessere?

Esistono solo due tipi di gruppi:

  • Gruppi multicolori :

    • Sono composti da 3 o 4 tessere.
    • Contengono solo tessere con lo stesso numero su di esse.
    • Tutte le piastrelle sono di diversi colori.
    • Esempio: RED 9, BLUE 9, BLACK 9.
  • Gruppi monocromatici :

    • Sono composti da almeno 3 tessere.
    • Non possono contenere più di 13 tessere.
    • Contengono solo tessere con numeri diversi e consecutivi su di esse, in ordine crescente.
    • Tutte le piastrelle hanno lo stesso colore.
    • Le tessere etichettate con 1 non possono essere posizionate dopo quelle etichettate 13.
    • Esempio: RED 5, RED 6, RED 7.

Aspetta, cosa fanno i Jolly?

I jolly possono sostituire qualsiasi pezzo del gioco. Ad esempio, il nostro primo esempio può diventare JOKER, BLUE 9, BLACK 9, RED 9, JOKER, BLACK 9o RED 9, BLUE 9, JOKER. Lo stesso vale per l'altro nostro esempio. Tuttavia, non si possono collocare due jolly nello stesso gruppo, quindi cose come JOKER, ORANGE 8, JOKERsono vietate.


Compito

Dato un gruppo di tessere Rummikub, determinare se è valido. Hai la garanzia che non verranno visualizzate tessere duplicate, ad eccezione dei 2 jolly e che le tessere che ricevi come input sono valide (ad es. Cose come 60non appariranno).

Input Output

È possibile accettare input e fornire output con qualsiasi metodo standard.

Alcuni formati di input validi: elenco di stringhe, elenco di tuple, elenchi nidificati, stringhe o qualsiasi altra cosa tu ritenga adatta. I colori possono essere presi come stringhe (ad es . "Blue","Red", etc.:), come abbreviazioni di stringhe (si prega di rendere distinguibili le piastrelle blu e nere) o come numeri interi corrispondenti a un colore. Quando si tratta di jolly, è necessario menzionare il modo in cui il programma li riceve come input. Se scegli le stringhe, potresti avere qualcosa di simile RED 9, JOKER, ..., se scegli le tuple che puoi avere (9,"RED"), ("JOKER")o qualcosa di equivalente. Se aiuta, potresti ricevere un colore per quel Joker (che non dovrebbe influenzare l'output del tuo programma). Ad esempio, potresti avere ("JOKER","RED")o ("JOKER","BLUE"), ma ciò non dovrebbe influenzare l'output in alcun modo.

Per quanto riguarda l'output, si applicano le regole standard per un .

Esempi lavorati

Facciamo un esempio, che si spera faciliterebbe la comprensione. Dato un gruppo come segue, in cui ogni tupla rappresenta una tessera:

[(9, "ROSSO"), (9, "ARANCIONE"), ("JOKER"), (9, "NERO")]

Questo dovrebbe restituire un valore di verità, perché l'input è valido. In questo caso, il Joker sostituisce (9, "BLUE")e formano un gruppo multicolore.

Se ti verrà dato il seguente gruppo:

[(9, "BLU"), (9, "ARANCIONE"), (9, "ROSSO"), (9, "NERO"), ("JOKER")]

Sarebbe invalido, e quindi il programma dovrebbe restituire un valore falso, perché non c'è nulla che il jolly possa sostituire, poiché il numero massimo di carte in un gruppo multicolore è 4.

Casi di prova aggiuntivi

Questi sono per una suite di test estesa che copre quasi tutte le possibili situazioni:

Ingresso -> Uscita 

[(1, "BLU"), (2, "BLU"), (3, "BLU"), (4, "BLU"), (5, "BLU"), (6, "BLU")] - > verità

[(6, "BLU"), (6, "ROSSO"), (6, "NERO)] -> verità

[(5, "nera"), (6, "nera"), (7 "nera"), (8, "nera"), (9, "nera"), (10, "nera"), ( "JOKER"), (12, "NERO")] -> verità 

[("JOKER"), (3, "BLU"), (3, "ROSSO")] -> verità

[(8, "NERO"), (2, "ROSSO"), (13, "BLU")] -> falsy

[(4, "ROSSO"), (3, "ROSSO"), (5, "ROSSO")] -> falsy

[(5, "NERO"), (6, "NERO)] -> falsy

[("JOKER"), (5, "RED"), ("JOKER")] -> falsy

[(4, "ROSSO"), (5, "ROSSO"), (6, BLU ")] -> falsy

[(4, "RED"), ("JOKER"), (5, "RED")] -> falsy

[(12, "NERO"), (13, "NERO), (1," NERO ")] -> falsy

Questo è , quindi vince il codice più breve in byte in ogni lingua!



Il furto è la parte migliore di rummikub. Anche senza questo sembra una sfida divertente.
Giosia,

[] È un input valido?
V. Courtois,

@ V.Courtois Certo.
Mr. Xcoder,

1
@ V.Courtois uno non può collocare due jolly nello stesso gruppo , quindi due un input contenente 2 jolly è errato.
Mr. Xcoder,

Risposte:


6

APL (Dyalog) , 58 byte

Prende un elenco di colori (1-4) come argomento destro e un elenco di numeri come argomento sinistro. Il numero di un Joker è indicato (⍳4)che equivale (1 2 3 4)a indicare che potrebbe essere uno di quelli. Allo stesso modo, il suo colore è indicato (⍳13)per indicare che potrebbe essere uno qualsiasi dei numeri da 1 a 13.

{(3≤≢⍺)∧((s⍵)∧⍺≡∪⍺)∨((s←{1∊≢∘∪¨⊃,¨/⍵})⍺)∧∨/∊(⊃,¨/⍵)⍷¨⊂⍳13}

Provalo online!

Algoritmo

Esistono tre condizioni, di cui le ultime due hanno due condizioni ciascuna:

  1. La corsa deve avere una lunghezza maggiore o uguale a 3

E NEMMENO

    1. un singolo numero AND

    2. colori unici

O

    1. un unico colore AND
    2. numeri sequenziali

affinché la corsa sia valida.

Ordine di lettura

3≤3 è inferiore o uguale al ≢⍺numero di tessere

e

   s⍵ tutti i numeri sono uguali

   e

   ⍺≡∪⍺ i colori sono unici

o

   1∊1 è tra ≢∘∪¨il numero di  colori ⊃,¨/espansi unici

   e

   ∨/esiste almeno uno tra tutti i ⊃,¨/⍵numeri espansi che ne eseguono ⍷¨⊂uno che si trova tra ⍳131 e 13

Spiegazione del codice completo

{... } funzione anonima dove è l'argomento sinistro ed è l'argomento giusto

3.2.

⍳13 i numeri da 1 a 13

(... )⍷¨trova le posizioni di partenza di ciascuna delle seguenti corse:

  ,¨/⍵ unisci ogni elemento dei numeri (crea una corsa per ogni valore di Joker)

   divulgare (perché /riduce il grado)

  ϵ nlist (appiattisci)

∨/ O riduzione (cioè sono vere?)

(... )∧ E:

3.1

  (... )⍺ il risultato dell'applicazione della seguente funzione nell'elenco dei colori:

   s←{... }s (per s AME), che è la seguente funzione anonima ( è il suo argomento):

    ,¨/⍵ unisci ogni elemento attraverso (crea una corsa per ogni valore di Joker)

     divulgare (perché /riduce il grado)

    ≢∘∪¨ il numero di elementi univoci in ciascun elenco

    1∊ uno è un membro? (cioè ci sono elenchi tutti uguali?)

(... )∨OPPURE:

2.2.

  ∪⍺ i colori unici

  ⍺≡ sono identici ai colori (ovvero sono unici)

  (... )∧ E:

2.1.

   s⍵ i numeri sono tutti uguali

  (... )∧E

1.

   ≢⍺ il numero di colori (ovvero il numero di tessere)

   3≤ tre è inferiore o uguale a quello


1
Wow, sembra che APL sia un ottimo strumento per questa sfida
Mr. Xcoder,

3

Gelatina , 41 40 38 36 byte

EȧI=1ȦȯE
0,W€yµZç/ɓQ⁼⁸ȧ
L>2ȧ4p13ðç€Ṁ

Provalo online! (viene fornito con un piè di pagina della suite di test)

Accetta input come array (color, value)per tessere normali e 0jolly. I colori sono rappresentati come numeri interi (anche se non sono sicuro che sia importante anche per il codice corrente).

Uscite 1(verità) o 0(falsa).

Spiegazione

L>2ȧ4p13ðç€Ṁ    Main link, checks if a sequence is valid. Args: sequence
L                 Get the length of the sequence.
 >2               Check if it's at least 3 tiles.
   ȧ4             And: yield 4 if it is, 0 otherwise.
     p13          Cartesian product: yield all possible tiles if
                  result was 4, empty array otherwise.
        ð         Begin a new dyadic chain with args (tiles, sequence).
         ç€       Call the first helper link for each tile with args (tile, sequence).

0,W€yµZç/ɓQ⁼⁸ȧ    First helper link, checks if a sequence is valid if jokers
                  are substituted for the given tile. Args: tile, sequence
0,                  Make a pair [0, tile].
  W€                Turn that into [[0], [tile]].
    y               Map all 0's (jokers) into tile in the sequence.
     µ              Begin a new monadic chain with args (sequence).
      Z             Transpose to get list [colors, values].
       ç/           Call the second helper link with args (colors, values).
         ɓ          Begin a new dyadic chain with args (sequence, valid).
          Q         Remove duplicate tiles from the sequence.
           ⁼⁸       Check if the sequence is unchanged (i.e. there were no duplicates).
             ȧ      And with the output of the second helper.

EȧI=1ȦȯE    Second helper link, checks if a sequence is valid assuming no duplicates.
            Args: colors, values
E             Check if all the colors are the same.
 ȧ            Logical and with the values array.
              Yields the values if they were, 0 if not.
  I           Find the differences between each value.
              Yields [] if the colors differed.
   =1         See if each difference is equal to 1.
              Yields [] if the colors differed.
     Ȧ        Check if the list was nonempty and all values were truthy.
              Yields 1 for valid mono-colors, 0 otherwise.
      ȯ       Logical or with the values array.
              Yields 1 for valid mono-colors, the values otherwise.
       E      Check if all the values are the same. For valid mono-colors
              this tests if all items of [1] are equal (obviously true).
              Yields 1 for valid sequences, 0 otherwise.

Penso che devi produrre una verità / falsità coerente.
Adám,

@ Adám Edited, fortunatamente non ha influenzato il conteggio dei byte.
PurkkaKoodari,

2

Python 2 , 371 370 362 341 329 325 byte

  • @ Mr.Xcoder ha salvato 1 byte: str.split()anzichélist literal
  • 8 byte salvati: scorciatoia per len(x)-1
  • 19 byte salvati: J O BK B Rper Joker, Orange, Black, Blue, Redvalori letterali
  • @ Mr.Xcoder ha salvato ancora altri 12 byte, grazie !!
  • Altri 4 byte grazie a @ Mr.Xcoder
def f(x):
 j=sum("J"in i for i in x);z=len(x)-1
 if j>1or z<2:return False
 if j<1:return(all(i[0]==x[0][0]for i in x)and sum(i[1]==x[0][1]for i in x)<2)or(all(i[1]==x[0][1]for i in x)and sum(int(x[m+1][0])==int(x[m][0])+1for m in range(z))==z)
 return any(f([[k,(i+1,j)]["J"in k]for k in x])for j in'RBbO'for i in range(13))

Provalo online!




1
Questo in realtà consente di risparmiare molti più byte di quanto pensassi: 329 .
Mr. Xcoder,

1
325 byte . Ci scusiamo per il miglioramento molto tardi .
Mr. Xcoder,

1

Javascript (ES6), 286 byte

var testcases = [[{n:1,c:"BLUE"},{n:2,c:"BLUE"},{n:3,c:"BLUE"},{n:4,c:"BLUE"},{n:5,c:"BLUE"}, {n:6,c:"BLUE"}],[{n:6,c:"BLUE"},{n:6,c:"RED"},{n:6,c:"BLACK"}],[{n:5,c:"BLACK"},{n:6,c:"BLACK"},{n:7,c:"BLACK"},{n:8,c:"BLACK"},{n:9,c:"BLACK"},{n:10,c:"BLACK"},{n:0,c:"JOKER"},{n:12,c:"BLACK"}],[{n:0,c:"JOKER"},{n:3,c:"BLUE"},{n:3,c:"RED"}],[{n:8,c:"BLACK"},{n:2,c:"RED"},{n:13,c:"BLUE"}],[{n:4,c:"RED"}, {n:3,c:"RED"}, {n:5,c:"RED"}],[{n:5,c:"BLACK"}, {n:6,c:"BLACK"}],[{n:0,c:"JOKER"},{n:5,c:"RED"},{n:0,c:"JOKER"}],[{n:4,c:"RED"},{n:5,c:"RED"},{n:6,c:"BLUE"}],[{n:4,c:"RED"},{n:0,c:"JOKER"},{n:5,c:"RED"}],[{n:12,c:"BLACK"},{n:13,c:"BLACK"},{n:1,c:"BLACK"}],[{n:11,c:"BLACK"},{n:12,c:"BLACK"},{n:0,c:"JOKER"}],[{n:1,c:"BLACK"},{n:2,c:"BLACK"},{n:3,c:"BLACK"},{n:1,c:"BLUE"},{n:2,c:"BLUE"},{n:3,c:"BLUE"}]];

g=a=>a.length
j=a=>a.n==0
l=(x,y)=>x.c==y.c||j(x)||j(y)
a=s=>g(s)>2&&([q=[0],x=s[0],s.map(y=>q[0]+=x==y||((l(x,y)||x.n==y.n)&&!(j(x)&&j(y)))&&(([n=s.indexOf(y),n<1||([x=s[n-1],!l(x,y)||y.n>0&&x.n<y.n])[1]||(n<g(s)-1&&x.n+1<s[n+1].n)||(n==g(s)-1&&y.n==0&&x.n<13)])[1])?1:0)])[0][0]==g(s)

testcases.forEach(H=>console.log(a(H)));

(Si noti che i casi di test sopra riportati contengono 2 casi di test aggiuntivi che non si trovano nella Domanda: sono rispettivamente veri e falsi: per la leggibilità, consultare la versione non registrata).

Processo di massima:

 Using first tile x:
   For each tile y:
     count for x: can group with y
 return: x matches n tiles, where n is the number of tiles

I jolly sono indicati con un 0valore numerico (funzionerebbe anche un numero negativo); ciò mantiene coerente la struttura di input (ha sia un colore che un valore) e non si basa sul fatto di dover verificare se c=="JOKER", salvando 7 byte.

È possibile che alcune parentesi possano essere rimosse, potrebbe non essere possibile boxare q come un array (l'ho provato e il valore è rimasto 0 o ha causato demoni nasali ).

Ungolfed:

var testcases = [
[{n:1,c:"BLUE"},{n:2,c:"BLUE"},{n:3,c:"BLUE"},{n:4,c:"BLUE"},{n:5,c:"BLUE"}, {n:6,c:"BLUE"}],//true
[{n:6,c:"BLUE"},{n:6,c:"RED"},{n:6,c:"BLACK"}],//true
[{n:5,c:"BLACK"},{n:6,c:"BLACK"},{n:7,c:"BLACK"},{n:8,c:"BLACK"},{n:9,c:"BLACK"},{n:10,c:"BLACK"},{n:0,c:"JOKER"},{n:12,c:"BLACK"}],//true
[{n:0,c:"JOKER"},{n:3,c:"BLUE"},{n:3,c:"RED"}],//true
[{n:8,c:"BLACK"},{n:2,c:"RED"},{n:13,c:"BLUE"}],//false
[{n:4,c:"RED"}, {n:3,c:"RED"}, {n:5,c:"RED"}],//false
[{n:5,c:"BLACK"}, {n:6,c:"BLACK"}],//false
[{n:0,c:"JOKER"},{n:5,c:"RED"},{n:0,c:"JOKER"}],//false
[{n:4,c:"RED"},{n:5,c:"RED"},{n:6,c:"BLUE"}],//false
[{n:4,c:"RED"},{n:0,c:"JOKER"},{n:5,c:"RED"}],//false
[{n:12,c:"BLACK"},{n:13,c:"BLACK"},{n:1,c:"BLACK"}],//false
[{n:11,c:"BLACK"},{n:12,c:"BLACK"},{n:0,c:"JOKER"}],//true
[{n:1,c:"BLACK"},{n:2,c:"BLACK"},{n:3,c:"BLACK"},{n:1,c:"BLUE"},{n:2,c:"BLUE"},{n:3,c:"BLUE"}]
];

g=a=>a.length
i=(a,v)=>a.indexOf(v)
j=x=>x.n==0
m=(x,y)=>
       (l(x,y)||x.n==y.n)
    &&!(j(x)&&j(y))
l=(x,y)=>x.c==y.c||j(x)||j(y)
c=(a,v)=>([n=i(a,v),
      n<1
    ||([x=a[n-1],!l(x,v)||v.n>0&&x.n<v.n])[1]
    ||(n<g(a)-1&&x.n+1<a[n+1].n)
    ||(n==g(a)-1&&v.n==0&&x.n<13)])[1]
a=s=>g(s)>2&&([q=[0],x=s[0],s.map(y=>q[0]+=x==y||m(x,y)&&c(s,y)?1:0)])[0][0]==g(s)

testcases.forEach(H=>console.log(a(H)));

Versione su cui ho lavorato per ottenere la logica corretta. Gli lambda monouso sono stati allineati; ecco la loro funzione corrispondente:

g() -> string.length
i() -> indexof
j() -> isJoker
m() -> do tiles match
l() -> do colors match
c() -> same-color isConsecutiveOrder
a() -> main lambda

1

C # (.NET Core) , 198 byte

using System.Linq;(C,N)=>{int l=C.Length,j=C.Count(x=>x<1),c=C.Distinct().Count(),n=N.Distinct().Count(),u=N.Min();foreach(var x in N)u*=0<(u&x)?2:0;return l>2&((u>0&n==l&c<2+j)|(n<2+j&c==l&l<5));};

Comprende i colori delle tessere e dei numeri su di essi come elenchi separati di numeri interi. Le specifiche di quella mappatura non contano finché ogni colore ha un intero diverso e i Jolly sono rappresentati come 0.

Il formato per l'immissione dei numeri è piuttosto speciale. Il numero che deve essere inserito per un numero nè invece 2 ^ n, mentre il numero usato per rappresentare un jolly dovrebbe essere (2 ^ 14) -1. Questo abilita bit u&xa bit e valuta se la piastrella x ha un valore uguale a te o è un jolly.

C # (.NET Core) , 200 byte

using System.Linq;(C,N)=>{int l=C.Length,j=N.Count(x=>x<1),c=C.Distinct().Count(),n=N.Distinct().Count(),u=N.Min();foreach(var x in N)u=u==x|x<1?u+1:0;return l>2&((u>0&n==l&c<2+j)|(n<2+j&c==l&l<5));};

Una soluzione più lunga di 2 byte che non è eclettica sull'input. Risulta solo usando un caso speciale per i jolly in un posto in cui erano difficili da affrontare non era molto più lungo dell'operazione intelligente bit a bit di cui ero così orgoglioso. Qui i jolly sono (0,0), altri numeri sono come attesi e i colori sono rappresentati con 4 valori distinti l'uno dall'altro dal confronto predefinito di C # (in particolare, il LinqDistinct() operazione deve considerare i valori per lo stesso colore come 'non distinti' e valori per diversi colori come 'distinti').

Qualcosa che potrebbe essere utile ad altre lingue, u*=!u++^x*xsarebbe equivalente u=u==x|x<1?u+1:0in alcune lingue; u ^ x è 0 iff u == x e 0 volte qualsiasi int è 0, quindi u ^ x * x sarebbe 0 per u == xo x == 0 se C # non effettuasse operazioni bit a bit con precedenza inferiore a quelli matematici. C # inoltre non può interpretare gli inte come bool senza casting esplicito. Una lingua che si sforza di far funzionare i tipi potrebbe convertire i valori 0e not 0in falsee trueprima di applicarli !però, e poi quando si torna a un int interpret !falsecome 1 e !truecome 0. Tutto ciò detto, non posso garantire che un'altra lingua in realtà beneficiare del resto dell'algoritmo, quindi potrebbe anche non emergere.


1

Scala, 491 477 caratteri, 491 477 byte

Questa sfida è stata divertente; Grazie.

var c=Seq("O","B","b","R")
t match{case _ if t.length<3=>false
case _ if t.exists(x=>x._1==0)=>{var b=false
if(t.filter(q=>q._1!=0).exists(q=>q._1==0))b else{for(y<-1 to 13)for(u<-c)b=b|f(t.takeWhile(q=>q._1!=0)++:(y,u)+:t.reverse.takeWhile(q=>q._1!=0).reverse)
b}}
case _::(x,_)::_ if t.forall(_._1==x)=>true
case _ if t.forall(_._2==c(0))|t.forall(_._2==c(1))|t.forall(_._2==c(2))|t.forall(_._2==c(3))=>(t(0)._1 to t(0)._1+t.length-1).toList equals t.map(_._1)
case _=>false}

Quindi falla riga 4 c'è una chiamata ricorsiva in cui provo a sostituire "JOKER" con ogni altra tessera. Vedi tio per una visione più chiara del codice. Ho scelto di prendere come input una sequenza di 2 tuple (Int, String) - chiamata tnel mio codice, vedi tio - così "JOKER" è rappresentato da una 2 tupla (0, "JOKER").

MODIFICA: 14 byte salvati grazie ai commenti, prendo OB b R per ARANCIONE NERO BLU ROSSO.

Provalo online!

MODIFICA: -2 byte, cancellati inutili (attorno alle condizioni della case _ ifs


Non puoi usare O,B,b,Rinvece di ORANGE,BLUE,BLACK,REDsalvare byte? Non ho idea di come funzioni Scala, ma penso che tu possa farlo.
Mr. Xcoder,

Provai; infatti salva i byte in questo modo (un seq di stringhe). Lo fa var (O,B,b,R)=("ORANGE","BLACK","BLUE","RED")e le chiamate sono O B b R, per un totale di 49 byte; dove var c=Seq("ORANGE","BLACK","BLUE","RED")e le chiamate c(...)totalizzano 58 byte. MA il primo caso lo permette for(u<-c)al posto di for(u<-Seq(O,B,b,R)), quindi il costo non è -9 ma +2. Grazie per averci provato.
V. Courtois,

@ V.Courtois Credo che ciò che il signor Xcoder stesse suggerendo stia usando var c=Seq("O","B","b","R")e prendendo quei caratteri come input piuttosto che stringhe complete per il colore. Come menzionato nel post originale, "I colori possono essere presi come ... Abbreviazioni di stringhe".
Kamil Drakari,

ohh ~ capisco cosa intendi, grazie a tutti e due
V. Courtois,
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.