Давайте пограємо в Румікуб!


11

Примітка. Це пов’язано з варіацією гри Rummikub


Передумови та правила

Rummikub - гра на основі плитки. Існує чотири кольори: червоний, помаранчевий, синій та чорний. Для кожного кольору є 13 плиток (марковані від 1 до 13), також є 2 джокера, які не залежать від кольору, отже, всього 54 штуки. У цій варіації Румікуба кожен гравець отримує 14 плиток і повинен отримати ще одну плитку і скинути ще одну в кожному раунді, таким чином, щоб кількість плиток була постійною. Гравці не бачать плиток один одного. Мета - згрупувати плитки так, щоб усі шматки належали принаймні до однієї групи (див. Нижче). Коли гравець згрупує всі шматки, вони скидають свою плиткову дошку і розкривають свої шматки. Потім інші перевіряють, чи всі комбінації дійсні, і якщо вони є, гравець виграє раунд.

Як можна згрупувати плитку?

Є лише два типи груп:

  • Багатоколірні групи:

    • Вони складаються з 3 або 4 плиток.
    • Вони містять лише плитки з однаковою кількістю на них.
    • Всі плитки мають різні кольори.
    • Приклад: RED 9, BLUE 9, BLACK 9.
  • Одноколірні групи:

    • Вони складаються щонайменше з 3 плиток.
    • Вони не можуть містити більше 13 плиток.
    • Вони містять лише плитки з різними послідовними номерами на них у порядку зростання.
    • Всі плитки мають однаковий колір.
    • Плитки, позначені маркуванням, 1 не можуть бути місцями після маркування плитки 13.
    • Приклад: RED 5, RED 6, RED 7.

Зачекайте, що роблять Джокери?

Джокери можуть замінити будь-яку частину гри. Наприклад, нашим першим прикладом може стати JOKER, BLUE 9, BLACK 9, RED 9, JOKER, BLACK 9або RED 9, BLUE 9, JOKER. Це ж стосується і іншого нашого прикладу. Тим НЕ менше, один може НЕ розмістити два джокера в одній і тій же групі, так що речі люблять JOKER, ORANGE 8, JOKERзаборонені.


Завдання

З огляду на групу плиток Румікуб, визначте, чи справді вона. Ви гарантуєте, що не буде показано жодних повторюваних плиток, за винятком двох джокерів і що плитки, які ви отримаєте як вхідні дані, дійсні (наприклад, такі речі, як, наприклад 60, не з’являться).

Введення-виведення

Ви можете взяти вклад і надати вихід будь-яким стандартним методом.

Деякі допустимі вхідні формати: список рядків, список кортежів, вкладені списки, рядки чи будь-що інше, що вам здається підходящим. Кольори можна сприймати як рядки (наприклад:) "Blue","Red", etc., як рядкові абревіатури (будь ласка, зробіть розрізнені сині та чорні плитки) або як цілі числа, що відповідають кольору. Що стосується Джокерів, то слід згадати те, як ваша програма приймає їх як вхідні дані. Якщо ви виберете Strings, у вас може виникнути щось на зразок RED 9, JOKER, ..., якщо ви виберете кортежі, які ви можете мати, (9,"RED"), ("JOKER")або щось еквівалентне. Якщо це допоможе, ви можете отримати колір для цього Джокера (який не повинен впливати на вихід вашої програми). Наприклад, у вас може бути ("JOKER","RED")або ("JOKER","BLUE"), але це ніяк не повинно впливати на вихід.

Щодо результату, застосовуються стандартні правила для .

Працювали приклади

Візьмемо приклад, який, сподіваємось, полегшить розуміння. Дано групу наступним чином, де кожен кортеж являє собою плитку:

[(9, "ЧЕРВОНІ"), (9, "ORANGE"), ("JOKER"), (9, "BLACK")]

Це повинно повернути триєдине значення, оскільки вхід правильний. У цьому випадку Джокер підміняє (9, "BLUE"), і вони утворюють багатоколірну групу.

Якщо вам дадуть таку групу:

[(9, "BLUE"), (9, "ORANGE"), (9, "RED"), (9, "BLACK"), ("JOKER")]

Це було б недійсно, і, таким чином, ви повинні програмі повернути хибне значення, оскільки жовтому джокеру не залишається нічого, як максимальна кількість карт у багатоколірній групі - 4.

Додаткові випробувальні випадки

Вони розроблені для розширеного тестового набору, який охоплює майже всі можливі ситуації:

Вхід -> Вихід 

[(1, "СВІТИЙ"), (2, "СВІТИЙ"), (3, "СВІТИЙ"), (4, "СВІТИЙ"), (5, "СВІТИЙ"), (6, "СВІТИЙ")] - > truthy

[(6, "СВІТИЙ"), (6, "ЧЕРВЕНИЙ"), (6, "ЧЕРНИЙ]] -> truthy

[(5, "ЧЕРНИЙ"), (6, "ЧЕРНИЙ"), (7, "ЧЕРНИЙ"), (8, "ЧОРНИЙ"), (9, "ЧЕРНИЙ"), (10, "ЧОРНИЙ"), ( "ДЖОКЕР"), (12, "ЧЕРНИЙ")] -> трибуна 

[("JOKER"), (3, "BLUE"), (3, "RED")] -> truthy

[(8, "ЧЕРНИЙ"), (2, "ЧЕРВОНІ"), (13, "СВІТИЙ")] -> хибність

[(4, "ЧЕРВЕНА"), (3, "ЧЕРВЕНА"), (5, "ЧЕРВЕНА")] -> хибність

[(5, "ЧЕРНИЙ"), (6, "ЧЕРНИЙ]] -> хибність

[("JOKER"), (5, "RED"), ("JOKER")] -> фальш

[(4, "КРАСНИЙ"), (5, "ЧЕРВЕНИЙ"), (6, СВІТИЙ)]] -> хибність

[(4, "ЧЕРВЕНИЙ"), ("ДЖОКЕР"), (5, "ЧЕРВЕНИЙ")] -> фальш

[(12, "ЧЕРНИЙ"), (13, "ЧЕРНИЙ), (1," ЧЕРНИЙ ")] -> хибний

Це , тому найкоротший код у байтах кожною мовою виграє!



Крадіжка - найкраща частина румікубу. Навіть без цього це виглядає як веселе завдання.
Йосія

Чи є [] дійсний вхід?
В. Куртуа

@ V.Courtois Звичайно.
Містер Xcoder

1
@ V.Courtois не може розмістити двох жартівників в одній групі , тому два входи, що містять 2 джокера, є хибними.
Містер Xcoder

Відповіді:


6

APL (Dyalog) , 58 байт

Список кольорів (1-4) приймає як правий аргумент, а список номерів - як лівий аргумент. Позначається номер Джокера, (⍳4)що еквівалентно (1 2 3 4)вказуванню на те, що воно може бути будь-яким із них. Так само позначається його колір, (⍳13)який вказує на те, що це може бути будь-яке з чисел від 1 до 13.

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

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

Алгоритм

Існує три умови, з яких дві останні мають дві умови:

  1. Пробіг повинен бути довжиною більше або дорівнює 3

І ВСЕ

    1. єдине число І

    2. унікальні кольори

АБО

    1. єдиний колір І
    2. послідовні числа

для того, щоб пробіг був дійсним.

Порядок читання

3≤3 менше або дорівнює ≢⍺кількості плиток

і

   s⍵ всі числа однакові

   і

   ⍺≡∪⍺ кольори унікальні

або

   1∊1 входить ≢∘∪¨до числа унікальних ⊃,¨/розширених  кольорів

   і

   ∨/серед усіх ⊃,¨/⍵розширених числових прогонів існує щонайменше один, ⍷¨⊂який знайдено в ⍳131-13

Повне пояснення коду

{} Анонімна функція, де лівий аргумент і правий аргумент

3.2.

⍳13 числа 1 - 13

()⍷¨Знайдіть початкові позиції кожного з наступних прогонів:

  ,¨/⍵ приєднатись до кожного елемента чисел (створює пробіг для кожного значення Джокера)

   розкрити (тому що /зменшує ранг)

  ϵ nlist (згладити)

∨/ АБО зменшення (тобто чи правда?)

()∧ І:

3.1

  ()⍺ Результат застосування наступної функції у списку кольорів:

   s←{}S (для s ame), яка є наступною анонімною функцією ( є її аргументом):

    ,¨/⍵ приєднати кожен елемент поперек (створює пробіг для кожного значення Джокера)

     розкрити (тому що /зменшує ранг)

    ≢∘∪¨ кількість унікальних елементів у кожному списку

    1∊ один член? (тобто чи є такі самі списки?)

()∨АБО:

2.2.

  ∪⍺ унікальні кольори

  ⍺≡ ідентичні кольорам (тобто вони унікальні)

  ()∧ І:

2.1.

   s⍵ номери всі однакові

  ()∧І

1.

   ≢⍺ кількість кольорів (тобто кількість плиток)

   3≤ три менше або дорівнює цьому


1
Нічого собі, схоже, що APL - чудовий інструмент для вирішення цього виклику
містер Xcoder

3

Желе , 41 40 38 36 байт

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

Спробуйте в Інтернеті! (поставляється із колонтитулом тестового набору)

Вводиться як масив (color, value)для звичайних плиток та 0для джокерів. Кольори представлені у вигляді цілих чисел (хоча я не впевнений, чи це має значення для поточного коду).

Вихідні дані 1(truthy) або 0(falesy).

Пояснення

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.

Я думаю, що вам доведеться вивести послідовну правду / хибність.
Адам

@ Adám Edited, на щастя, не вплинуло на кількість байтів.
PurkkaKoodari

2

Python 2 , 371 370 362 341 329 325 байт

  • @ Mr.Xcoder зберег 1 байт: str.split()замістьlist literal
  • 8 байтів збережено: стенограма для len(x)-1
  • Збережено 19 байт: J O BK B Rдля Joker, Orange, Black, Blue, Redлітералів
  • @ Mr.Xcoder врятував ще 12 байт, дякую !!
  • Ще 4 байти завдяки @ 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))

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




1
Це фактично економить набагато більше байтів, ніж я думав: 329 .
Містер Xcoder

1
325 байт . Вибачте за дуже пізнє покращення.
Містер Xcoder

1

Javascript (ES6), 286 байт

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

(Зверніть увагу, що тестові приклади, наведені вище, містять 2 додаткові тестові випадки, які не містяться у Питання: вони є правдивими та хибними відповідно: див. Для нечитабельності версію).

Грубий процес:

 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

Джокери позначаються 0як їх числове значення (негативне число також буде працювати); це підтримує структуру введення послідовною (має і колір, і значення) і не покладається на те, щоб перевіряти c=="JOKER", зберігаючи 7 байт.

Можливо, що деякі дужки можуть бути видалені, можливо, це не буде поле, qяк масив (я спробував це, і значення просто або залишилося 0, або викликало назальних демонів ).

Безголівки:

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

Версія, над якою я працював, щоб виправити логіку. Лямбди для одноразового використання вбудовані; ось їх відповідна функція:

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 байт

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));};

Розглядає кольори плиток і цифри на них як окремі списки цілих чисел. Специфіка цього відображення не має значення, якщо кожен колір має інше ціле число, а Джокери представлені як 0.

Хоча формат для введення цифр досить особливий. Число, яке потрібно ввести для числа n, замість цього становить 2 ^ n, тоді як число, яке використовується для представлення джокера, має бути (2 ^ 14) -1. Це дозволяє розрядно і u&xоцінити u, якщо плитка x має значення, рівне u, або джокер.

C # (.NET Core) , 200 байт

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));};

На два байти довше рішення, яке не еклектично щодо введення. Виявляється просто використання спеціального випадку для жартівників в одному місці, з яким важко було впоратися, не набагато довше, ніж розумна побіжна операція, якою я так пишався. Тут Джокери (0,0), інші цифри, як очікувалося, а кольори представлені будь-якими 4 значеннями, які відрізняються один від одного порівнянням за замовчуванням C # (конкретно, Distinct()операція Linq повинна враховувати значення для одного кольору як "не відрізняти" і значення для різних кольорів як "відмінні").

Щось, що може бути корисним для інших мов, u*=!u++^x*xбуло б еквівалентно u=u==x|x<1?u+1:0в деяких мовах; u ^ x дорівнює 0 iff u == x, і 0 разів будь-який int дорівнює 0, тому u ^ x * x буде 0 або для u == x або x == 0, якщо C # не зробить побітові операції нижчим пріоритетом, ніж математичні. C # також не може інтерпретувати вставки як булі без явного кастингу. Мова, яка намагається зробити типи роботи, може перетворити значення 0і not 0до, falseі trueдо їх застосування !, але потім, повертаючись до int інтерпретувати !falseяк 1 і !trueяк 0. Все, що сказано, я не можу гарантувати, що інша мова насправді буде користь від решти алгоритму, тому він може навіть не вийти.


1

Scala, 491 477 символів, 491 477 байт

Цей виклик був веселим; Дякую.

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}

Тож fу рядку 4 - рекурсивний дзвінок, де я намагаюся замінити "JOKER" на будь-яку іншу плитку. Дивіться tio для більш чіткого перегляду коду. Я вибрав взяти за вхід послідовність 2-кортежів (Int, String) - викликається tв моєму коді, див. Tio - тому "JOKER" представлений двома кортежами (0, "JOKER").

EDIT: 14 байтів, збережених завдяки коментарям, я беру OB b R за ORANGE BLACK BLUE RED.

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

EDIT: -2 ​​байти, видалено марно (в умовах case _ ifs


Ви не можете використовувати O,B,b,Rзамість цього, ORANGE,BLUE,BLACK,REDщоб зберегти байти? Я поняття не маю, як працює Скала, але я думаю, що ви можете.
Містер Xcoder

Я намагався; насправді це економить байти, роблячи таким чином (послідовність рядків). Це робить var (O,B,b,R)=("ORANGE","BLACK","BLUE","RED")і викликає O B b Rзагалом 49 байт; де var c=Seq("ORANGE","BLACK","BLUE","RED")і викликає c(...)загальний обсяг 58 байт. АЛЕ перший дозвіл дозволяє for(u<-c)замість for(u<-Seq(O,B,b,R)), тому вартість не -9, а +2. Дякуємо, що спробували.
В. Куртуа

@ V.Courtois Я вважаю, що містер Xcoder пропонує використовувати var c=Seq("O","B","b","R")і використовувати ці символи як свої введення, а не повні рядки для кольору. Як було сказано в оригінальному дописі, "Кольори можна сприймати як ... Рядок абревіатур".
Каміль Дракарі

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