Torne este jogo de dados justo


8

Esse desafio é adaptado da Olimpíada Britânica de Informática .


Jogo de dados

Dois jogadores estão jogando um jogo de dados em que cada um deles joga um par de dados e a soma mais alta vence. Os pares de dados têm o mesmo número de lados, mas não precisam ter os mesmos valores de cada lado. Portanto, o jogo é justo se, para ambos os pares de dados, todas as somas possíveis puderem ser feitas com igual probabilidade.

Por exemplo, se o Jogador 1 tiver os seguintes dados:

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

Em seguida, eles podem produzir as seguintes somas:

    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

Se o jogador 2 tiver:

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

Eles podem produzir:

    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

Este jogo é justo, já que o mínimo para ambos é 2, o máximo é 12 e cada soma ocorre o mesmo número de vezes, por exemplo, 7 podem ser feitas de 6 maneiras com cada par.


Desafio

Escreva um programa / função que use dois dados como entrada e, opcionalmente, um número inteiro representando o número de lados que cada dado contém e imprima / retorne um par diferente de dados que poderia ser usado para jogar um jogo justo com os dois dados de entrada, ou qualquer valor falsey se não houver solução diferente da entrada.


Especificações

  • O número de lados em ambos os dados deve ser o mesmo e igual ao número de lados no par de dados de entrada. Esse número sempre será um número inteiro maior ou igual a 1.

  • Os dois dados retornados podem ser os mesmos, mas o par não deve ser o mesmo que o par de entrada.

  • Pares de pedidos diferentes não são diferentes; {1,2,3} {4,5,6} é o mesmo que {4,5,6} {1,2,3}.

  • Seu programa não precisa produzir um resultado rapidamente, desde que acabe produzindo uma saída correta.

  • Os valores no par de dados de entrada sempre serão números inteiros entre 1 e 9, inclusive, mas os valores retornados podem ser qualquer número inteiro ≥1.

  • Se houver mais de uma solução possível, apenas uma deverá ser devolvida.

  • Entrada / Saída pode estar em qualquer formato razoável.

Casos de teste

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
Dados de três lados parecem legais: images2.sw-cdn.net/product/picture/…
Magic Octopus Urn

O dado conterá apenas dígitos ou também pode ser maior que 9? Eu só vejo decisões sobre os lados >=1, mas existe um máximo? Se for maior que 9, você se importaria de adicionar um caso de teste para ele?
21717 Kevin Murrijssen

@KevinCruijssen Atualizado, a entrada conterá apenas dígitos, a saída pode conter qualquer número inteiro ≥1.
Trelzevir 15/03/19

Respostas:


2

Geléia , 34 bytes

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

Retorna uma lista de todos os pares possíveis de dados até a ordenação de dados e faces * (excluindo os que são os mesmos dados que o par de entrada).

Experimente online!

Este é um forçador bruto e não é eficiente (muito lento para executar o caso de teste de 6 faces no TIO).

+þµ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.

* ou seja, se [[1,1,4,4],[1,1,5,5]]é uma possibilidade (como em um dos exemplos), não haverá uma [[1,1,5,5],[1,1,4,4]ou[[1,4,1,4],[1,1,5,5]] , etc.


Hmm, eu realmente assumi que os dados estarão na ordem do rosto (ou os dados primeiro), está tudo bem ou não?
Jonathan Allan

... Percebi que um caso de teste tem um dado que não está ordenado, então removi a suposição.
Jonathan Allan

1

C ++ 14, 130 bytes

Como lambda sem nome, assumindo Mser como std::vector<std::vector<int>>. Justo é 0, qualquer outra coisa é injusta.

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

Ungolfed:

#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 bytes

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]

Isso foi há muito tempo; Eu provavelmente poderia jogar isso um pouco melhor agora.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.