このサイコロゲームを公正にする


8

この課題は、英国情報学オリンピックから採用されました。


サイコロゲーム

2人のプレイヤーがサイコロゲームをプレイし、それぞれが1対のサイコロを振って、最高額が勝ちます。サイコロのペアは同じ数の辺を持っていますが、各辺で同じ値を持っている必要はありません。したがって、両方のサイコロのペアについてすべての可能な合計が等しい確率で作成できる場合、ゲームは公平です。

たとえば、プレーヤー1に次のダイスがあるとします。

{1,2,3,4,5,6} {1,2,3,4,5,6}

次に、次の合計を生成できます。

    1  2  3  4  5  6
 +------------------
1|  2  3  4  5  6  7 
2|  3  4  5  6  7  8
3|  4  5  6  7  8  9
4|  5  6  7  8  9  10
5|  6  7  8  9  10 11
6|  7  8  9  10 11 12

プレーヤー2が持っている場合:

{1,2,2,3,3,4} {1,3,4,5,6,8}

彼らは生成することができます:

    1  2  2  3  3  4
 +------------------
1|  2  3  3  4  4  5 
3|  4  5  5  6  6  7
4|  5  6  6  7  7  8
5|  6  7  7  8  8  9
6|  7  8  8  9  9  10
8|  9  10 10 11 11 12

このゲームは、両方の最小値が2、最大値が12であり、各合計が同じ回数発生するので公平です。たとえば、各ペアで7を6通りにすることができます。


チャレンジ

2つのダイスを入力として受け取り、オプションで各ダイスに含まれるサイドの数を表す整数を受け取り、2つの入力ダイスを使用して公正なゲームをプレイするために使用できる異なるペアのダイスを印刷/返すプログラム/関数を記述します。入力と異なる解がない場合は、誤った値。


仕様書

  • 両方のサイコロの辺の数は同じでなければならず、サイコロの入力ペアの辺の数と等しくなければなりません。この数は常に1以上の整数になります。

  • 返される2つのサイコロは同じでもかまいませんが、ペアは入力ペアと同じであってはなりません。

  • 注文ペアが異なっても違いはありません。{1,2,3} {4,5,6}は{4,5,6} {1,2,3}と同じです。

  • 最終的に正しい出力を生成する限り、プログラムは結果を迅速に生成する必要はありません。

  • サイコロの入力ペアの値は常に1から9までの整数ですが、返される値は1以上の任意の整数にすることができます。

  • 可能な解決策が複数ある場合は、1つだけを返す必要があります。

  • 入力/出力は適切な形式にすることができます。

テストケース

6
1 2 2 3 3 4
8 6 5 4 3 1

1 2 3 4 5 6
1 2 3 4 5 6

4
1 1 1 1
1 4 5 8

1 1 4 4
1 1 5 5

3
1 3 5
2 4 6

False

8                    
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8

Any of the following:

1 2 2 3 3 4 4 5       |    1 2 2 3 5 6 6 7   |    1 2 3 3 4 4 5 6
1 3 5 5 7 7 9 11      |    1 3 3 5 5 7 7 9   |    1 2 5 5 6 6 9 10

3
3-面ダイスはクールに見える:images2.sw-cdn.net/product/picture/...
— マジックタコ壺

サイコロには数字しか含まれていないの9でしょうか、それともそれよりも高いのでしょうか?私は側面についての判決を見るだけ>=1ですが、上限はありますか?9を超える場合は、テストケースを追加してもよろしいですか?
— Kevin Cruijssen 2017年

@KevinCruijssen更新。入力には数字のみが含まれ、出力には1以上の任意の整数を含めることができます。
— Trelzevir 2017年

回答:


2

ゼリー、34 バイト

+þµFṢ
ç©ṀRœċL}Œċµç/⁼®µÐf
,Ṣ€,Ṛ$ḟ@ç

サイコロと面の順序までのすべての可能なサイコロのペアのリストを返します(入力ペアと同じサイコロを除く)。

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

これはブルートフォーサーであり、効率的ではありません(TIOで6面のテストケースを実行するには遅すぎます)。

+þµFṢ - Link 1, sorted sums: dieA, dieB
 þ    - outer product with
+     -     addition (make a table of the sums, a list of lists)
  µ   - monadic chain separation
   F  - flatten into one list
    Ṣ - sort

ç©ṀRœċL}Œċµç/⁼®µÐf - Link 2, all possible fair dice pairs (including input): dieA, dieB
ç                  - call the last link (1) as a dyad
 ©                 - save the result to the register for later use too
  Ṁ                - maximum (the largest sum)
   R               - range [1,2,...,maxSum]
       }           - use right argument (dice B) to turn the monad into a dyad:
      L            -     length
    œċ             - all combinations with replacement (i.e. all dice with faces between 1 and maxSum inclusive [overkill, but golfier than less])
        Œċ         - all pairs of these dice
          µ        - monadic chain separation
               µÐf - filter keep:
            /      -     reduce with:
           ç       -         last link (1) as a dyad (the sorted sums of the current pair)
              ®    -     retrieve register value (the sorted sums of the input pair)
             ⁼     -     equal?

,Ṣ€,Ṛ$ḟ@ç - Main link: dieA, dieB
,         - pair - [dieA, dieB]
 Ṣ€       - sort €ach - [dieASorted, dieBSorted]
     $    - last two links as a monad:
    Ṛ     -     reverse - [dieBSorted, dieASorted]
   ,      -     pair - [[dieASorted, dieBSorted], [dieBSorted, dieASorted]]
        ç - call the last link (2) as a dyad (with dieA, dieB)
       @  - reversed @rguments:
      ḟ   -     filter out - removes any results that are equivalent to the input pair.

*つまり[[1,1,4,4],[1,1,5,5]]、可能性がある場合(例の1つにあるように)[[1,1,5,5],[1,1,4,4]や[[1,4,1,4],[1,1,5,5]]などはありません。


うーん、私は実際にサイコロが面順になると仮定しました(どちらかが先に)。それで大丈夫ですか?
— ジョナサンアラン

...テストケースに注文されていないダイがあることに気付いたので、仮定を削除しました。
— ジョナサンアラン

1

C ++ 14、130バイト

名前のないラムダのMように仮定しますstd::vector<std::vector<int>>。公正は0、その他は不公正です。

#include<map>
[](auto&M){auto g=[](auto&v){std::map<int,int>m;for(int x:v)for(int y:v)m[x+y]++;return m;};return g(M[0])-g(M[1]);}

未ゴルフ:

#include<map>

auto f=
[](auto&M){
 auto g=[](auto&v){
  std::map<int,int>m;
  for(int x:v)
   for(int y:v)
    m[x+y]++;
  return m;
 };
 return g(M[0])==g(M[1]);
}
;

1

Python、228バイト

from itertools import*;s,C=lambda x,y:sorted(sum([[i+j for j in y]for i in x],[])),combinations_with_replacement;f=lambda k,l,m:([[*a]for a in C([*C([*range(1,s(l,m)[-1])],k)],2)if(s(l,m)==s(*a))*~-([*a]in[[l,m],[m,l]])]+[0])[0]

これはずっと前からのものです。私はおそらくこれをもう少し良くゴルフすることができたでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.