Prepare-se para morrer?

22

fundo

Uma fonte de tédio nos RPGs de mesa é lidar com jogadas envolvendo muitos dados. Lançar um feitiço de desintegração pode ser instantâneo, mas rolar e somar 40 dados certamente não é!

Várias sugestões para lidar com isso são discutidas em rpg.stackexchange.com . Alguns deles, no entanto, como o uso de um programa de rolagem ou a média de dados, retiram parte da diversão e senso de controle dos jogadores. Outros, como rolar 4 dados e multiplicar o total por 10, tornam os resultados muito mais instáveis ​​(enquanto a média dos dados age na direção oposta).

Esta questão diz respeito a um método de reduzir o número de jogadas de dados sem alterar o resultado médio (média) ou sua oscilação (variação).

Notação e matemática

Nesta pergunta, usaremos a seguinte notação para representar lançamentos de dados:

  • n d k (por exemplo 40d6) refere-se à soma de n rolos de fieira k lados.
  • n d k * c (por exemplo, 4d6 * 10) descreve a multiplicação do resultado por uma constante c.
  • Também podemos adicionar rolos (por exemplo, 4d6 * 10 + 40d6) e constantes (por exemplo, 4d6 + 10).

Para um único rolo de matriz, podemos mostrar que:

  • Média : E [1d k ] = (k + 1) / 2
  • Variância : Var (1d k ) = (k-1) (k + 1) / 12

Usando as propriedades básicas de média e variância, podemos ainda inferir que:

  • Média : E [ m d k * a + n d l * b + c ] = am .E [1d k ] + bn . [1d l ] + c
  • Variância : Var ( m d k * a + n d l * b + c ] = a ². M. Var (1d k ) + b ². N .Var (1d l )

Tarefa

Dado três números inteiros n , k e r , seu programa deve gerar uma maneira de aproximar n d k no máximo de r rolos, com as seguintes restrições:

  • A solução deve ter a mesma média e variação que n d k .
  • A solução deve conter o maior número possível de rolos menor ou igual a r , pois mais rolos produz uma distribuição mais suave.
  • Você deve restringir suas soluções a usar apenas dados do lado k , a menos que esteja buscando o bônus (veja abaixo).
  • Se não houver solução (como r é muito pequeno), o programa deve exibir a sequência "EU SOU UM DEUS DA GUERRA SEM SEXY!".
  • Os parâmetros são passados ​​como uma única sequência separada por espaço.
  • Você pode assumir que 1 ≤ n ≤ 100, 1 ≤ rn e que k é um dos 4, 6, 8, 10, 12 e 20 (os dados padrão usados ​​nas mesas).
  • A saída deve estar no formato descrito em Notação (por exemplo, 4d6 * 10 + 5), com espaços opcionais em torno de + s, mas em nenhum outro lugar. Os multiplicadores de unidades também são opcionais: 4d6 * 1 e 4d6 são válidos.

Você pode escrever um programa ou função, recebendo informações via STDIN (ou alternativa mais próxima), argumento de linha de comando ou argumento de função. Os resultados devem ser impressos em STDOUT (ou alternativa mais próxima) ou retornados como uma sequência.

Exemplos

>> "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!

Pontuação

O menor código vence. Aplicam-se regras padrão.

Bônus

-33% (arredondado antes da subtração) se o seu programa também retornar soluções que incluam dados válidos que não sejam k (onde os valores válidos, como mencionado acima, são 4, 6, 8, 10, 12 e 20). Se você optar por fazê-lo, sempre retorne essas soluções quando apropriado e lide com soluções que usem vários tipos de matriz. Exemplo:

>> "7 4 3"
3d6+7
Uri Granta
fonte
6
+1 Para a referência OotS. ;) (Bem e porque é realmente um bom desafio, na verdade).
Martin Ender
11
Talvez use nossos novos recursos de $ \ LaTeX $ para exibir essa questão?
Orlp
2
@UriZarfaty: atualizei suas fórmulas para usar o LaTeX. Espero que esteja tudo bem. Se você não gostar, basta reverter a postagem e ela voltará ao que era antes.
Alex A.
11
Revirei a edição do LaTeX, porque, infelizmente, ela será desativada novamente por enquanto .
22815 Martin Ender
11
#SadPanda - Eu pensei que isso seria uma referência de desafio de código para "Olá. Meu nome é Inigo Montoya. Você matou meu pai. Prepare-se para morrer".
scunliffe

Respostas:

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

Demonstração online

Quando não se misturam tipos de dados, o problema se reduz a expressar ncomo uma soma de não mais que rquadrados e ké irrelevante, exceto pelo cálculo da constante no final. A maior parte desta resposta é a contabilidade necessária para expressar o resultado no formato desejado: o cálculo real é ^\?,{^base}%{0\{.*+}/^=},para encontrar os factores de multiplicação a, betc .; e ^@{-}/@)*.2/para calcular a constante.

Dissecação

~                # 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
fonte
1

Python, 487 461 452 - 33% = 303 bytes

Como ninguém mais o fez, aqui está uma solução que lida com diferentes tipos de dados. Como a outra solução, gera uma variedade de soluções possíveis e as filtra. Ele usa o fato de que (k + 1) (k-1) = k ^ 2-1 e duas semi-brechas na especificação (oops!): A falta de proibição de imprimir a forma redundante 0d k * a (o que economiza todos os 5 bytes!) e a falta de restrição de tempo de execução (fica lento muito rapidamente, embora execute todos os exemplos fornecidos).

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 uma saída mais bonita, adicione if x[0]depois "%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
fonte