Haz que este juego de dados sea justo

8

Este desafío está adaptado de la Olimpiada británica de informática .


Juego de dados

Dos jugadores están jugando un juego de dados donde cada uno tira un par de dados, y gana la suma más alta. Los pares de dados tienen el mismo número de lados, pero no tienen que tener los mismos valores en cada lado. Por lo tanto, el juego es justo si para ambos pares de dados todas las sumas posibles se pueden hacer con la misma probabilidad.

Por ejemplo, si el Jugador 1 tiene los siguientes dados:

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

Luego pueden producir las siguientes sumas:

    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

Si el jugador 2 tiene:

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

Pueden producir:

    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 juego es justo, ya que el mínimo para ambos es 2, el máximo es 12 y cada suma se produce el mismo número de veces, por ejemplo, 7 se pueden hacer 6 formas con cada par.


Desafío

Escriba un programa / función que tome dos dados como entrada, y opcionalmente un número entero que represente el número de lados que contiene cada dado, e imprima / devuelva un par diferente de dados que podrían usarse para jugar un juego justo con los dos dados de entrada, o cualquier valor falsey si no hay una solución diferente de la entrada.


Especificaciones

  • El número de lados en ambos dados debe ser el mismo e igual al número de lados en el par de dados de entrada. Este número siempre será un número entero mayor o igual a 1.

  • Los dos dados devueltos pueden ser iguales, pero el par no debe ser el mismo que el par de entrada.

  • Los diferentes pares de órdenes no son diferentes; {1,2,3} {4,5,6} es lo mismo que {4,5,6} {1,2,3}.

  • Su programa no necesita producir un resultado rápidamente, siempre y cuando finalmente produzca la salida correcta.

  • Los valores en el par de dados dados siempre serán enteros entre 1 y 9 inclusive, pero los valores devueltos pueden ser cualquier número entero ≥1.

  • Si hay más de una solución posible, solo debe devolverse una.

  • La entrada / salida puede estar en cualquier formato razonable.

Casos de prueba

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
Trelzevir
fuente
3
Los dados de 3 lados se ven geniales: images2.sw-cdn.net/product/picture/…
Magic Octopus Urn el
¿El dado solo contendrá dígitos, o también puede ser más alto que 9? Solo veo una decisión sobre los lados >=1, pero ¿hay un máximo? Si puede ser superior a 9, ¿le importaría agregar un caso de prueba?
Kevin Cruijssen
@KevinCruijssen Actualizado, la entrada solo contendrá dígitos, la salida puede contener cualquier número entero ≥1.
Trelzevir

Respuestas:

2

Jalea , 34 bytes

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

Devuelve una lista de todos los pares de dados posibles hasta el orden de dados y caras * (excluyendo cualquiera que sea el mismo dado que el par de entrada).

Pruébalo en línea!

Este es un forzador de fuerza bruta, y no es eficiente (demasiado lento incluso para ejecutar el caso de prueba de 6 caras en 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.

* es decir, si [[1,1,4,4],[1,1,5,5]]es una posibilidad (como en uno de los ejemplos) no habrá un [[1,1,5,5],[1,1,4,4]o [[1,4,1,4],[1,1,5,5]], etc.

Jonathan Allan
fuente
Hmm, he asumido que los dados estarán en orden de cara (ya sea el dado primero), ¿está bien o no?
Jonathan Allan
... Noté que un caso de prueba tiene un dado que no está ordenado, así que eliminé la suposición.
Jonathan Allan
1

C ++ 14, 130 bytes

Como lambda sin nombre suponiendo Mque sea así std::vector<std::vector<int>>. Lo justo es que 0cualquier otra cosa es 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]);}

Sin golf:

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

Esto fue de hace mucho tiempo; Probablemente podría jugar golf un poco mejor ahora.

0WJYxW9FMN
fuente