¿Prepárate para morir?

22

Fondo

Una fuente de tedio en los juegos de rol de mesa es lidiar con tiradas que involucran muchos dados. Lanzar un hechizo de desintegración puede ser instantáneo, ¡pero lanzar y sumar 40 dados ciertamente no lo es!

Se discuten varias sugerencias para manejar esto en rpg.stackexchange.com . Sin embargo, algunos de ellos, como usar un programa de lanzamiento o promediar dados, les quitan algo de diversión y sentido de control a los jugadores. Otros, como lanzar 4 dados y multiplicar el total por 10, hacen que los resultados sean mucho más oscilantes (mientras que el promedio de los dados actúa en la dirección opuesta).

Esta pregunta se refiere a un método para reducir el número de tiradas de dados sin cambiar el resultado promedio (media) o su oscilación (varianza).

Notación y matemática

En esta pregunta, usaremos la siguiente notación para representar tiradas de dados:

  • n d k (p. ej., 40d6) se refiere a la suma de n tiradas de un dado de k lados.
  • n d k * c (por ejemplo, 4d6 * 10) describe la multiplicación del resultado por una constante c.
  • También podemos agregar rollos (por ejemplo, 4d6 * 10 + 40d6) y constantes (por ejemplo, 4d6 + 10).

Para un solo dado, podemos mostrar que:

  • Media : E [1d k ] = (k + 1) / 2
  • Varianza : Var (1d k ) = (k-1) (k + 1) / 12

Usando las propiedades básicas de media y varianza, podemos inferir además que:

  • Media : E [ m d k * a + n d l * b + c ] = am .E [1d k ] + bn . [1d l ] + c
  • Varianza : Var ( m d k * a + n d l * b + c ] = a ². M .Var (1d k ) + b ². N .Var (1d l )

Tarea

Dados tres enteros n , k y r , su programa debería generar una forma de aproximar n d k en la mayoría de los rollos r , con las siguientes restricciones:

  • La solución debe tener la misma media y varianza que n d k .
  • La solución debe contener el mayor número posible de rollos menor o igual a r , ya que más rollos producen una distribución más suave.
  • Debes restringir tus soluciones a solo usar dados k -sided, a menos que estés apuntando a la Bonificación (ver más abajo).
  • Si no hay solución (ya que r es demasiado pequeño), el programa debería generar la cadena "¡SOY UN DIOS DE GUERRA SEXY SHOELESS!".
  • Los parámetros se pasan como una sola cadena separada por espacios.
  • Puede suponer que 1 ≤ n ≤ 100, 1 ≤ rny que k es uno de 4, 6, 8, 10, 12 y 20 (los dados estándar utilizados en las mesas).
  • La salida debe estar en el formato descrito en Notación (por ejemplo, 4d6 * 10 + 5), con espacios opcionales alrededor de + s pero en ningún otro lugar. Los multiplicadores de unidades también son opcionales: tanto 4d6 * 1 como 4d6 son válidos.

Puede escribir un programa o función, tomando datos a través de STDIN (o la alternativa más cercana), argumento de línea de comandos o argumento de función. Los resultados deben imprimirse en STDOUT (o la alternativa más cercana) o devolverse como una cadena.

Ejemplos

>> "10 6 10"
10d6
>> "10 6 4"
2d6*2+2d6+14
>> "10 6 3"
1d6*3+1d6+21
>> "10 6 2"
1d6*3+1d6+21
>> "10 6 1"
I AM A SEXY SHOELESS GOD OF WAR!

Tanteo

El código más corto gana. Aplican reglas estándar.

Prima

-33% (redondeado hacia abajo antes de la resta) si su programa también devuelve soluciones que incluyen dados válidos distintos de k (donde los valores válidos, como se mencionó anteriormente, son 4, 6, 8, 10, 12 y 20). Si elige hacerlo, siempre debe devolver dichas soluciones cuando sea apropiado y manejar soluciones que usan múltiples tipos de troqueles. Ejemplo:

>> "7 4 3"
3d6+7
Uri Granta
fuente
66
+1 Para la referencia de OotS. ;) (Bueno, y porque es un desafío realmente agradable, en realidad.)
Martin Ender
1
¿Quizás usar nuestras nuevas capacidades $ \ LaTeX $ para cambiar esta pregunta?
orlp
2
@UriZarfaty: Actualicé tus fórmulas para usar LaTeX. Espero que esté bien. Si no te gusta, puedes retroceder la publicación y volverá a ser como era antes.
Alex A.
1
Revertí la edición de LaTeX, porque desafortunadamente, se desactivará nuevamente por ahora .
Martin Ender
1
#SadPanda - Pensé que esto sería una referencia de desafío de código para "Hola. Mi nombre es Iñigo Montoya. Mataste a mi padre. Prepárate para morir".
scunliffe

Respuestas:

5

GolfScript ( 163 143 133 bytes)

~@:^\?,{^base 0-}%{0\{.*+}/^=},.{{,}$-1=..&{[[1$[1$]/,(3$@]'d*+'1/]zip}%^@{-}/@)*.2/\1&'.5'*}{];'I AM A SEXY SHOELESS GOD OF WAR!'}if

Demostración en línea

Cuando no se mezclan tipos de dados, el problema se reduce a expresarse ncomo una suma de no más que rcuadrados, y kes irrelevante, excepto para el cálculo de la constante al final. La mayor parte de esta respuesta es la contabilidad requerida para expresar el resultado en el formato deseado: el cálculo real es ^\?,{^base}%{0\{.*+}/^=},encontrar los factores de multiplicacióna , betc .; y ^@{-}/@)*.2/para calcular la constante.

Disección

~                # Stack: n k r
@:^\?,{          # Store n in ^, and for 0 to n**r
  ^base 0-       #   convert to base n and remove 0s.
}%               # Stack: k [arrays of up to r values from 1 to n-1]
{0\{.*+}/^=},    # Filter them to arrays whose sum of squares is n,
                 #   i.e. to multipliers which have the right variance
.{               # If any multiplier array passes the filter...
  {,}$-1=        #   Pick one with the greater number of rolls
                 #   Stack: k [multipliers]
  ..&{           #   Map each distinct multiplier a...
    [[           #     Gather in nested array for later zip
      1$[1$]/,(  #       Split a copy of the multipliers around a to count the as
                 #       Let's denote that count as m
                 #       Stack: k [multipliers] a [ [ m
      3$@        #       Copy k and rotate the a inside the nested array
     ]           #       Stack: k [multipliers] [ [m k a]
      'd*+'1/    #       Push an array ['d' '*' '+'] and close nested array
    ]zip         #       Giving [[m 'd'] [k '*'] [a '+']]
                 #       which will be printed as mdk*a+
  }%             #   Stack: k [multipliers] [string representations of dice]
  ^@{-}/@)*      #   Compute (n - sum(multipliers)) * (k + 1)
                 #   That's twice the constant we need to add to fix the mean
  .2/\1&'.5'*    #   And convert it to a renderable form, including .5 if needed
}{               # Otherwise clear the stack and push the error message
  ];'I AM A SEXY SHOELESS GOD OF WAR!'
}if
Peter Taylor
fuente
1

Pitón, 487 461 452 - 33% = 303 bytes

Como nadie más lo ha hecho, aquí hay una solución que maneja diferentes tipos de dados. Al igual que la otra solución, genera una gama de posibles soluciones y las filtra. Utiliza el hecho de que (k + 1) (k-1) = k ^ 2-1 y dos semi-lagunas en la especificación (¡Uy!): La falta de prohibición de imprimir la forma redundante 0d k * a (lo que ahorra todos de 5 bytes!), y la falta de restricción de tiempo de ejecución (se ralentiza bastante rápido, aunque ejecuta todos los ejemplos dados).

from itertools import*
N,K,R=map(int,input().split())
S=lambda l:sum([x[0]for x in l])
s=[x for x in product(*[[(n,k,a)for n in range(N*(K**2-1)/((k**2-1)*a**2)+1)]for a in range(1,N+1)for k in[4,6,8,10,12,20]if a**2<=N])if sum([n*(k**2-1)*a**2 for n,k,a in x])==N*K**2-N and S(x)<=R]
if s:s=max(s,key=S);print"+".join(["%sd%s*%s"%x for x in s]+[str(int(N*(K+1)/2.-sum([n*a*(k+1)/2.for n,k,a in s])))])
else:print"I AM A SEXY SHOELESS GOD OF WAR!"

Para una salida más bonita, agregue if x[0]después de "%sd%s*%s"%x for x in s:

>> "7 4 3"
3d6+7
>> "10 6 3"
1d6*1+1d8*1+1d8*2+18
>> "10 6 2"
1d6*1+1d6*3+21
>> "10 6 1"
I AM A SEXY SHOELESS GOD OF WAR!
Uri Granta
fuente