13

これは実際には麻雀ベースの質問ですが、Rommeベースまたはポーカーベースの背景でも簡単に理解できます。

麻雀では、14枚の牌(牌はポーカーのカードのようなもの)が4セットと1組に配置されています。通り( "123")は、常に正確に3つのタイルを使用しますが、それ以上でもそれ以下でもありません。同じ種類のセット(「111」)も、正確に3つのタイルで構成されています。これにより、合計3 * 4 + 2=14タイルになります。

ここでは関係のないKanや13Orphansのようなさまざまな例外があります。色と値の範囲(1〜9)もアルゴリズムにとって重要ではありません。

私は、上記のように手を配置できるかどうかを判断しようとしています。特定の理由で、14だけでなく、任意の数のタイルを処理できる必要があります。(次のステップは、ハンドを完了するために交換する必要のあるタイルの数を見つけることです。)

例:

11122233344455-簡単、4セットとペア。
12345555678999--123、456、789、555、99-123、123、789、888、99-有効なハンドではありませ
11223378888999
11223344556789

私の現在の、まだ実装されていないアイデアは次のとおりです。タイルごとに、a)通りb)セットc)ペアを作成してみてください。何も機能しない場合(またはペアが1つを超える場合)、前の反復に戻って次のオプションを試すか、これが最高レベルの場合は失敗します。それ以外の場合は、残りのタイルのリストから使用済みのタイルを削除して、次の反復を続行します。

このアプローチは機能し、適度に高速であると思います(パフォーマンスは「素晴らしいボーナス」です)が、これについてのあなたの意見に興味があります。別の解決策を考えられますか?これまたは類似のものはすでに存在しますか?

(宿題ではなく、麻雀を習っています。

4

3 に答える 3

17

通りとセットの値の合計は、3 で割ることができます。

  • n + n + n = 3n
  • (n-1) + n + (n + 1) = 3n

したがって、解決されたハンドのすべての数字を合計すると、3N + 2M の形式の数字が得られます。ここで、M はペアのタイルの値です。3 による除算の余り ( total % 3) は、M の各値に対して次のようになります。

total % 3 = 0  -> M = {3,6,9}
total % 3 = 1  -> M = {2,5,8}
total % 3 = 2  -> M = {1,4,7}

したがって、9 つの可能なペアをテストする代わりに、単純な追加に基づいて 3 つのペアを試すだけで済みます。可能なペアごとに、その値を持つ 2 つのタイルを削除し、アルゴリズムの次のステップに進み、可能かどうかを判断します。

これを取得したら、最も低い値から始めます。その値を持つタイルが 3 つ未満の場合、それらは必ず通りの最初の要素であることを意味するため、その通りを削除します (タイル n+1 または n+2 が見つからないために削除できない場合は、ハンドを意味します)。は無効)、次に低い値に進みます。

最小値のタイルが 3 つ以上ある場合は、それらをまとめて削除します (「それらが道路の一部だったらどうなるか?」と尋ねる場合は、そうであればタイル n+1 の 3 つと 3 つのタイルもあると考えてください)。セットに変えることもできるタイルn + 2の)そして続けます。

空の手札に到達した場合、その手札は有効です。

たとえば、無効なハンドの合計は 60 で、M = {3,6,9} を意味します。

Remove the 3: 112244556789
 - Start with 1: there are less than three, so remove a street
   -> impossible: 123 needs a 3

Remove the 6: impossible, there is only one

Remove the 9: impossible, there is only one

2 番目の例12345555678999では、合計は 78 です。つまり、M = {3,6,9} です。

Remove the 3: impossible, there is only one

Remove the 6: impossible, there is only one

Remove the 9: 123455556789
 - Start with 1: there is only one, so remove a street
   -> 455556789
 - Start with 4: there is only one, so remove a street
   -> 555789
 - Start with 5: there are three, so remove a set
   -> 789
 - Start with 7: there is only one, so remove a street
   -> empty : hand is valid, removals were [99] [123] [456] [555] [789]

3 番目の例 11223378888999 にも合計 78 があるため、バックトラッキングが発生します。

Remove the 3: 11227888899
 - Start with 1: there are less than three, so remove a street
   -> impossible: 123 needs a 3

Remove the 6: impossible, there are none

Remove the 9: 112233788889
 - Start with 1: there are less than three, so remove streets
   -> 788889
 - Start with 7: there is only one, so remove a street
   -> 888
 - Start with 8: there are three, so remove a set
   -> empty, hand is valid, removals were : [99] [123] [123] [789] [888]
于 2010-11-11T14:06:40.293 に答える
3

それを正しくするためにいくつかの再作業を行う必要がある特別なケースがあります。これは、ランオブスリーと同じ値 (ただしスートが異なる) のペアがある場合に発生します。

b が竹、c が文字、d が点を表すとすると、次の手を試してください。

b2,b3,b4,b5,b6,b7,c4,c4,c4,d4,d4,d6,d7,d8

d4,d4 should serve as the pair, and c4,c4,c4 should serve as the run-of-3 set.

しかし、3 つの「c4」タイルが 2 つの d4 タイルの前に表示されるため、最初の 2 つの c4 タイルがペアとして選択され、孤立した c4 と 2 つの d4 が残り、これら 3 つのタイルは有効なセットを形成しません。

この場合、2 つの c4 タイルを手札に「戻し」(手札をソートしたままにして)、基準 (値 == 4) を満たす次のタイルを検索する必要があります。そのためには、c4 を試行したことをコードに「記憶」させる必要があるため、次の反復では c4 をスキップして、値 == 4 の他のタイルを探す必要があります。コードは少し面倒ですが、実行可能です。

于 2012-10-31T04:52:05.820 に答える
1

私はそれを2つのステップに分けます。

  1. 可能な組み合わせを考えます。これらの数値で網羅的なチェックが可能だと思います。このステップの結果は組み合わせのリストで、各組み合わせにはタイプ (セット、ストリート、またはペア) と、使用されるカードのパターン (ビットマップの場合もあります) があります。
  2. 前の情報を使用して、可能な組み合わせのコレクションを決定します。ここでビットマップが役に立ちます。ビット単位の演算子を使用すると、異なるコンビネータで同じタイルを使用する際に重複が見られる場合があります。

ステップ 1.5 を実行して、各タイプが十分に利用可能かどうかを確認することもできます。このステップとステップ 2 で、一般的なアルゴリズムを作成できます。最初のステップは、すべての数のタイルと可能な組み合わせで同じです。

于 2010-11-11T14:06:24.607 に答える