何を待っていますか?(麻雀ソルバー)


13

チャットでのディスカッションから@MartinBüttnerに感謝します

麻雀は、アジアで非常に人気のあるタイルゲームです。通常、4人のプレイヤーでプレイされ、ゲームの目標は、タイルを使用して有効なハンドを完了する最初の人になることです。この課題では、ゲームの簡易バージョンであるPPCG麻雀を検討します。

PPCG麻雀には3つのスーツがあります- mpそしてs-タイルはから1まで番号が付けられてい9ます。各タイルのコピーは正確に4つあり、タイルは番号とそれに続くスーツ(たとえば3m9s)で示されます。

完成したPPCG麻雀ハンドは、3セットと4セットで構成され、合計14タイルです。

3つのセットは次のいずれかです。

  • 同じタイルの3つ(たとえば4s 4s 4s、ではない4m 4p 4s)、または
  • 同じスーツ内の3つの連続したタイルのシーケンス(例:1s 2s 3sor 6p 7p 8pnot 3s 4m 5mor or 3p 5p 7p)。シーケンスはラップしません(9m 1m 2m無効です)。

ペアは、単純に2つの同一のタイルです(例:)5s 5s

チャレンジ

プログラムには、13個のタイルのスペースで区切られた手が届き、各タイルは4回までしか表示されません。完全なプログラムまたは文字列を受け取る関数のいずれかを記述できます。

あなたの仕事は、ハンドに追加すると完成したPPCG麻雀ハンドを形成する可能性のあるすべての14番目のタイル(「待機」)を見つけることです。出力されるタイルはスペースで区切る必要がありますが、順序は任意です。先頭または末尾の空白は許可されます。

プログラムは、1分以内で妥当な時間内に実行する必要があります。

Input: 1m 1m 1m 4s 4s 4s 7p 7p 7p 3m 3m 3m 9s
Output: 9s

Input: 1m 1m 1m 3m 3m 3m 5m 5m 5m 2s 3s 7p 8p
Output:

Input: 1m 2m 2m 3m 3m 3m 3m 4m 1s 1s 9s 9s 9s
Output: 1s

Input: 1m 1m 1m 2m 3m 4m 5m 6m 7m 8m 9m 9m 9m
Output: 1m 2m 3m 4m 5m 6m 7m 8m 9m

Input: 1m 1m 1m 5p 2m 3m 5p 7s 8s 5p 9s 9s 9s
Output: 1m 4m 6s 9s 

最初の例では、1m 4s 7p 3mすべてが既存のトリプレット9sを形成し、孤立してペアを形成します。

2番目の例では、2s 3sand 7p 8pはシーケンスのみを形成でき、残りのタイルはトリプレットのみを形成できます。したがって、ペアを形成することはできず、出力はありません。

3番目の例では、手がに分割され1m2m3m 2m3m4m 3m3m 1s1s 9s9s9sます。通常、これはの待機になりますが、3m 1s4つすべて3mが使用されているため、使用可能な待機はのみです1s

4番目の例では、すべてのmタイルがハンドを完成させます。たとえば、の場合、完成したハンドを1m持ち1m1m1m 1m2m3m 4m5m6m 7m8m9m 9m9mます。

4番目の例と5番目の例の残りの部分を試してみてください:)

得点

これはであるため、最小バイト数のソリューションが優先されます。標準の抜け穴が適用されます。


9
麻雀という言葉を聞くたびに西洋人が考えると思われるタイルを使用した(IMOの迷惑な)ソリティアではなく、実際に麻雀をしてくれてありがとう。
ジャスティン14年

@Quincunx Fun fact:この挑戦は、麻雀ソリティアのASCII表現を使って挑戦したかったからです(ある時点ではまだそうするかもしれません...)。私はそれを「麻雀ソリティア」と呼んでいました。;)
マーティン・エンダー14年

2
@Quincunx:それは彼らのせいではないと思います。それは、彼らの「麻雀ソリティア」ゲームを「麻雀」と呼んだことに対するゲーム開発者の責任です。
ジョーZ. 14年

7ペアはどうですか?13人の孤児?あなたは名誉でさらに複雑なことをすることができます:) シャンペンテンパイを獲得する前に必要な最小限のタイル-勝つ準備ができている)を計算するように求めるコードゴルフを作成すると、それは目的外だと思いますか?
V.クルトワ

@VCourtois久しぶりですが、ゲームに慣れていない人の挑戦を過度に複雑にしないために、7ペア、13人の孤児、名誉を除外し、すでに電話をかけたことを特に覚えています。その後、シャンテンチャレンジを行うことを検討しましたが、最終的にはしませんでした。投稿したい場合は、すばらしいチャレンジになると思います。
Sp3000

回答:


4

Python、 312 281バイト

def W(S):H=lambda C,n=0,t=1:sum([m<C[0]and H([c-s for c in C][:l]+C[l:],n+1,u)for m,s,l,u in(2,3,1,t),(t,2,1,4),(4-5*all(C[:3]),1,3,t)])|H(C[1:],n,t)if C[2:]and max(C)<5else n>4;T=[i+s for s in"mps"for i in"12345678900"];return" ".join(t for t in T if("1"<t)*H(map((S+t).count,T)))

W 入力として文字列を受け取り、出力として文字列を返します。

タイルの数が少ない(27)ため、各タイルがハンドを完了するかどうかをテストするのに十分な速さです。問題は、ハンドが有効かどうかをチェックすることです。この関数は、セットのすべての可能な選択を考慮し、それらのいずれかが完全なハンドになるかどうかをチェックする単純なバックトラッキングアルゴリズムを使用します。

手はタイルヒストグラム、つまりタイルカウントのリストとして表されます(手に存在するものだけでなく、すべてのタイルについて)。これにより、特定の数の特定のタイルがあるかどうかと、隣接するタイルのシーケンスがあります(異なるスーツのタイル間のパディングはマルチスーツシーケンスを防ぎます)。


ああ、あなたは私を倒す:あなたが使用できるようにPはとにかく、それが見えるmapように、場所のカップルで:H(map((S+t).count,T))
FryAmTheEggman

@FryAmTheEggmanそれを逃しました。ありがとう!
エルは

@ Sp3000 Python 2です。それは奇妙です。2.7.8では問題なく動作します。
エル14年

@Ellは2.7.8で動作します-2.7.5は5elseが好きではありませんでした:P
Sp3000 14年

2

JavaScript(E6)306

F=h=>(
  R=(a,p,n=1)=>(a=[...a]).splice(p,n)&&a,
  K=(t,d=3)=>
    !t[0]
    |t.some(
      (v,p)=>
        v==t[p+1]&v==t[p+d-1]&&
        K(R(t,p,d))
      ||
        ~((r=t.indexOf((x=-~v[0])+v[1]))|(s=t.indexOf(-~x+v[1])))&&
        K(R(R(R(t,s),r),p))
    ),
  o=[],
  [for(s of'mps')for(i of'123456789')h.replace(t=i+s,s,'g')[34]
  &&K([t,...h.split(' ')].sort(),2)&&o.push(t)
  ],o
)

説明した

F=hand=>(
  Remove=(a,p,n=1)=>                // function to remove 1 or more element from an array, returning a new shorter array
    ((a=[...a]).splice(p,n), a),    // using array.splice on a new created array 

  Check=(ckHand, dim)=>  // recursive function to check hand. 
                         // removing pairs (at iteration 0) or sequence of three, if at last the hand remain empty then success
                         // parameter dim is 2 or 3 indicating how many equal elements are to be removed
    !ckHand[0]           // check if empty (element 0 does not exist)
    |ckHand.some(        // else traverse all array checking what can be removed
      (value, position)=> 
        value == ckHand[position + 1] 
        & value == ckHand[position + dim-1] &&   // look for 3 (or 2) equal elements
        Check(Remove(ckHand, position, dim), 3)   // if found, then remove elements and check again
      ||
        ~((r = ckHand.indexOf((x=-~value[0]) + value[1]))     // value[0] is number, value[1] is suit 
        |(s = ckHand.indexOf(-~x + value[1]))) &&              // look for an ascending sequence in following elements (the array is sorted)
        Check(Remove(Remove(Remove(ckHand, s), r), position),3) // if sequence found, remove elements and check again
    ),
  output=[], // start with an empty solution list
  [ // using array comprehension to implement a double loop
    for(s of'mps')        // loop for all suits
    for(i of'123456789')  // loop for all numbers
    (
       tile=i+s, // current tile 
       (hand.replace(tile,' ','g').length > 34)      // if tile is present 4 times in hand, the replaced length is 38-4 == 34
       && (                                       // else proceed with check
         ckHand = hand.split(' '), 
         ckHand.push(tile),    // in ckHand (as an array) the hand to be checked, that is base hand + current tile
         ckHand.sort(),        // sorting the array simplfy the checks
         Check(ckHand, 2)      // start checks looking for a pair
       )
       && 
         output.push(tile)   // if check ok, add tile to the solution list
    )   
  ],
  output // last expression in list is the function return value 
)

FireFox / FireBugコンソールでテストする

;["1m 1m 1m 4s 4s 4s 7p 7p 7p 3m 3m 3m 9s", "1m 1m 1m 3m 3m 3m 5m 5m 5m 2s 3s 7p 8p",
 "1m 2m 2m 3m 3m 3m 3m 4m 1s 1s 9s 9s 9s", "1m 1m 1m 2m 3m 4m 5m 6m 7m 8m 9m 9m 9m",
 "1m 1m 1m 5p 2m 3m 5p 7s 8s 5p 9s 9s 9s"].forEach(s=>console.log(s+' => '+F(s)))

出力

1m 1m 1m 4s 4s 4s 7p 7p 7p 3m 3m 3m 9s => 9s
1m 1m 1m 3m 3m 3m 5m 5m 5m 2s 3s 7p 8p =>
1m 2m 2m 3m 3m 3m 3m 4m 1s 1s 9s 9s 9s => 1s
1m 1m 1m 2m 3m 4m 5m 6m 7m 8m 9m 9m 9m => 1m,2m,3m,4m,5m,6m,7m,8m,9m
1m 1m 1m 5p 2m 3m 5p 7s 8s 5p 9s 9s 9s => 1m,4m,6s,9s
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.