ルミクブを遊ぼう!


11

注:これはゲームRummikubのバリエーションに関連しています


背景とルール

Rummikubはタイルベースのゲームです。赤、オレンジ、青、黒の4色があります。各色には13のタイル(1から13までのラベルが付いています)があり、色に依存しない2つのジョーカーもあるため、合計で54個になります。このRummikubのバリエーションでは、各プレーヤーは14タイルを受け取り、タイルの数が一定になるように、ラウンドごとに1つのタイルを取得し、別のタイルを1つずつドロップする必要があります。プレイヤーはお互いのタイルを見ることはありません。目標は、すべてのピースが少なくとも1つのグループに属するようにタイルをグループ化することです(以下を参照)。プレーヤーがすべてのピースをグループ化すると、タイルボードをドロップして、ピースを公開します。他の人は、すべての組み合わせが有効かどうかを確認し、有効な場合は、プレイヤーがラウンドに勝利します。

タイルをどのようにグループ化できますか?

グループには2つのタイプしかありません。

  • マルチカラーグループ:

    • 彼らは3つまたは4つのタイルで構成されています。
    • 同じ番号のタイルのみが含まれています。
    • すべてのタイルは異なる色です。
    • 例:RED 9, BLUE 9, BLACK 9
  • 単色グループ:

    • それらは少なくとも3つのタイルで構成されます。
    • 13個を超えるタイルを含めることはできません。
    • それらには、昇順で異なる連続番号のタイルのみが含まれます。
    • すべてのタイルは同じ色です。
    • でラベル付けされたタイルは、でラベル付けされたタイルの後に配置され1 ない場合があります13
    • 例:RED 5, RED 6, RED 7

待って、ジョーカーは何をしますか?

ジョーカーはゲームのどの部分でも代用できます。たとえば、最初の例は JOKER, BLUE 9, BLACK 9RED 9, JOKER, BLACK 9またはになりRED 9, BLUE 9, JOKERます。同じことが他の例にも当てはまります。ただし、同じグループに2人のジョーカーを配置することはできないため、このようなことJOKER, ORANGE 8, JOKERは禁止されています。


仕事

Rummikubタイルグループを指定して、それが有効かどうかを判断します。2つのジョーカーを除いて、重複するタイルが表示されないこと、および入力として受け取ったタイルが有効であること(たとえば、60表示されないようなもの)が保証されます。

入出力

入力を取り、標準的な方法で出力を提供できます。

いくつかの有効な入力形式:文字列のリスト、タプルのリスト、ネストされたリスト、文字列、またはその他の適切なもの。色は"Blue","Red", etc.文字列(例:)、文字列の省略形(青と黒のタイルを区別できるようにしてください)、または色に対応する整数として取得できます。ジョーカーに関しては、プログラムが入力として受け取る方法について言及する必要があります。文字列を選択した場合、のようなものRED 9, JOKER, ...、可能性のあるタプル(9,"RED"), ("JOKER")または同等のものが選択された可能性があります。それが役立つ場合は、そのジョーカーの色を受け取ることがあります(プログラムの出力に影響しないはずです)。たとえば、("JOKER","RED")または("JOKER","BLUE")があっても、出力には何の影響もありません。

出力に関しては、標準ルールが適用されます。

実施例

理解しやすくなるように、例を挙げましょう。次のようにグループが与えられた場合、各タプルはタイルを表します。

[(9、 "RED")、(9、 "ORANGE")、( "JOKER")、(9、 "BLACK")]

入力は有効であるため、これは真実の値を返すはずです。この場合、ジョーカーがに置き換わり(9, "BLUE")、それらはマルチカラーグループを形成します。

次のグループが与えられた場合:

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

マルチカラーグループのカードの最大数は4であるため、ジョーカーに代わるものは何もないので、それは無効であり、したがって、プログラムは偽の値を返す必要があります。

追加のテストケース

これらは、考えられるほとんどすべての状況をカバーする拡張テストスイート用です。

入力->出力 

[(1、 "青")、(2、 "青")、(3、 "青")、(4、 "青")、(5、 "青")、(6、 "青")]- >真実

[(6、 "BLUE")、(6、 "RED")、(6、 "BLACK)]->真実

[(5、 "BLACK")、(6、 "BLACK")、(7、 "BLACK")、(8、 "BLACK")、(9、 "BLACK")、(10、 "BLACK")、( "JOKER")、(12、 "BLACK")]->真実 

[( "JOKER")、(3、 "BLUE")、(3、 "RED")]->真実

[(8、 "BLACK")、(2、 "RED")、(13、 "BLUE")]->偽物

[(4、 "RED")、(3、 "RED")、(5、 "RED")]->偽物

[(5、 "BLACK")、(6、 "BLACK)]->偽物

[( "JOKER")、(5、 "RED")、( "JOKER")]->偽物

[(4、 "RED")、(5、 "RED")、(6、BLUE ")]->偽物

[(4、 "RED")、( "JOKER")、(5、 "RED")]->偽物

[(12、 "BLACK")、(13、 "BLACK)、(1、" BLACK ")]->偽物

これはなので、すべての言語でバイト単位の最短コードが優先されます。



盗むことはrummikubの最良の部分です。それなしでも、これは楽しい挑戦のように見えます。
ジョサイア

[]は有効な入力ですか?
V.クルトワ

@ V.Courtoisもちろんです。
Xcoder氏2017

1
@ V.Courtois 2つのジョーカーを同じグループ配置することはできないため、2つの入力に2つのジョーカーが含まれていると誤解を招きます。
Xcoder氏2017

回答:


6

APL(Dyalog)、58バイト

右側の引数として色のリスト(1〜4)を取り、左側の引数として数値のリストを受け取ります。ジョーカーの番号が示さ(⍳4)(1 2 3 4)ています。これは、それらのいずれかである可能性があることを示すのと同じです。同様に、その色は(⍳13)、1から13までの任意の数字である可能性があることを示すために示されています。

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

オンラインでお試しください!

アルゴリズム

3つの条件があり、そのうち最後の2つにはそれぞれ2つの条件があります。

  1. ランの長さは3以上でなければなりません

そしてどちらか

    1. 単一の番号

    2. ユニークな色

または

    1. 単色AND
    2. 連番

実行を有効にするため。

読み順

3≤ 3は以下 ≢⍺タイル数

そして

   s⍵ すべての数字は同じです

   そして

   ⍺≡∪⍺ 色はユニークです

または

   1∊1は≢∘∪¨ユニークな⊃,¨/拡張数  色の

   そして

   ∨/1から13で見つかるすべての⊃,¨/⍵拡張された数の実行のうち少なくとも1つ存在⍷¨⊂⍳13

完全なコードの説明

{… が左引数で右引数} である無名関数

3.2。

⍳13 1から13までの数字

()⍷¨次の各実行の開始位置を見つけます。

  ,¨/⍵ 数値の各要素を結合します(各ジョーカー値の実行を作成します)

   開示する(/ランクを下げるため)

  ϵ nlist(平坦化)

∨/ OR削減(つまり、本当ですか?)

(…そして)∧ :

3.1

  ()⍺ 色のリストに次の関数を適用した結果:

   s←{... }S(のため以下の匿名関数であるAME)(あるその引数):

    ,¨/⍵ 各要素を結合します(各Joker値の実行を作成します)

     開示する(/ランクを下げるため)

    ≢∘∪¨ 各リストの一意の要素の数

    1∊ メンバーですか?(つまり、まったく同じリストはありますか?)

()∨または:

2.2。

  ∪⍺ ユニークな色

  ⍺≡ 色と同じである(つまり、色が異なる)

  (…そして)∧ :

2.1。

   s⍵ 数字はすべて同じです

  (... )∧

1。

   ≢⍺ 色の数(タイルの数など)

   3≤ 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(真実)または0(偽)。

説明

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.

私はあなたが一貫した真実/虚偽を出力する必要があると思います。
アダム2017

@Adám編集済み。幸い、バイト数には影響しませんでした。
PurkkaKoodari 2017

2

パイソン2371の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バイトを節約しました。ありがとう!!
  • @ Mr.Xcoderのおかげでさらに4バイト
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氏2017

1
325バイト非常に遅い改善のため申し訳ありません。
Xcoder氏2017

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つの追加のテストケースが含まれていることに注意してください。これらはそれぞれtrueとfalseです。読みやすいように、非ゴルフバージョンを参照してください)。

大まかなプロセス:

 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、数値としてa を持つことで示されます(負の数でも機能します)。これにより、入力構造体の一貫性が保たれ(ColorとValueの両方を持ちます)、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&xxが有効になり、タイルxの値がuと等しいかジョーカーである場合に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));};

入力に関して折衷的ではない2バイト長いソリューション。ジョーカーの特別なケースを1つの場所で使用するだけで解決できなかったことが判明しました。ここで、ジョーカーは(0,0)であり、他の数値は期待どおりであり、色は、C#のデフォルト比較(具体的には、LinqDistinct()操作は同じ色の値を「区別しない」と見なす必要があります)および「異なる」としての異なる色の値)。

他の言語で役立つかもしれない何かは、いくつかの言語でu*=!u++^x*x同等u=u==x|x<1?u+1:0です。u ^ xは、u == xの場合は0であり、intが0の場合は0であるため、C#がビット単位の演算の優先順位を低くしない場合、u == xまたはx == 0のいずれかでu ^ x * xは0になります。数学的なもの。C#では、明示的なキャストを行わないと、intをブール値として解釈できません。試行が困難なタイプの仕事が値を変換可能性があるようにすることを言語0not 0するfalseと、true適用する前に、!けれども彼らにして、intに背を行くときの解釈!false1とし、!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」は2タプル(0、「JOKER」)で表されます。

編集:コメントのおかげで14バイト節約されました、私はオレンジブラックブルーレッドのためにOB b Rを取ります。

オンラインでお試しください!

編集:-2バイト、役に立たない削除 (case _ if sの条件の周りの


バイトを節約するO,B,b,R代わりに使用できませんORANGE,BLUE,BLACK,REDか?Scalaがどのように機能するかはわかりませんが、できると思います。
Xcoder氏2017

私は試した; 実際、この方法でバイト数を節約します(一連の文字列)。ありvar (O,B,b,R)=("ORANGE","BLACK","BLUE","RED")、呼び出しはO B b R、合計49バイトです。where var c=Seq("ORANGE","BLACK","BLUE","RED")とcallはc(...)合計58バイトです。ただし、最初のケースfor(u<-c)ではの代わりに許可されるfor(u<-Seq(O,B,b,R))ため、コストは-9ではなく+2になります。試していただきありがとうございます。
V.クルトワ

@ V.Courtois Xcoder氏が提案していたことはvar c=Seq("O","B","b","R")、色の完全な文字列ではなく、これらの文字を入力として使用および取得することだと思います。元の投稿で述べたように、「色は...文字列の省略形と見なすことができます」。
カミルドラカリ2017

ああ〜私はあなたの意味がわかります、@両方の人に感謝します
V. Courtois
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.