Distribuição de frequência de rolos de dados mistos

24

Um acompanhamento para este desafio

Dado um conjunto de dados mistos, produza a distribuição de frequências rolando todos eles e somando os números rolados em cada dado.

Por exemplo, considere 1d12 + 1d8(rolar 1 dado de 12 lados e 1 dado de 8 lados). Os rolos máximo e mínimo são 20e 2, respectivamente, semelhantes ao rolamento 2d10(2 dados de 10 lados). No entanto, 1d12 + 1d8resulta em uma distribuição mais plana do que 2d10: [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 2, 1]versus [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1].

Regras

  • As frequências devem ser listadas em ordem crescente da soma à qual a frequência corresponde.
  • É permitido rotular as frequências com as somas correspondentes, mas não é obrigatório (pois as somas podem ser deduzidas da ordem necessária).
  • Você não precisa manipular entradas nas quais a saída excede o intervalo representável de números inteiros para o seu idioma.
  • Zeros à esquerda ou à direita não são permitidos. Somente frequências positivas devem aparecer na saída.
  • Você pode receber a entrada em qualquer formato razoável (lista de dados ( [6, 8, 8]), lista de pares de dados ( [[1, 6], [2, 8]]), etc.).
  • As frequências devem ser normalizadas para que o GCD das frequências seja 1 (por exemplo, em [1, 2, 3, 2, 1]vez de [2, 4, 6, 4, 2]).
  • Todos os dados terão pelo menos uma face (então a d1é o mínimo).
  • Isso é , então o código mais curto (em bytes) vence. As brechas padrão são proibidas, como de costume.

Casos de teste

Esses casos de teste são dados como input: output, onde a entrada é fornecida como uma lista de pares [a, b]representando a bdados de lados (isso [3, 8]se refere 3d8e [[1, 12], [1, 8]]se refere a 1d12 + 1d8).

[[2, 10]]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[[1, 1], [1, 9]]: [1, 1, 1, 1, 1, 1, 1, 1, 1]
[[1, 12], [1, 8]]: [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 2, 1]
[[2, 4], [3, 6]]: [1, 5, 15, 35, 68, 116, 177, 245, 311, 363, 392, 392, 363, 311, 245, 177, 116, 68, 35, 15, 5, 1]
[[1, 3], [2, 13]]: [1, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 37, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 1]
[[1, 4], [2, 8], [2, 20]]: [1, 5, 15, 35, 69, 121, 195, 295, 423, 579, 761, 965, 1187, 1423, 1669, 1921, 2176, 2432, 2688, 2944, 3198, 3446, 3682, 3898, 4086, 4238, 4346, 4402, 4402, 4346, 4238, 4086, 3898, 3682, 3446, 3198, 2944, 2688, 2432, 2176, 1921, 1669, 1423, 1187, 965, 761, 579, 423, 295, 195, 121, 69, 35, 15, 5, 1]
[[1, 10], [1, 12], [1, 20], [1, 50]]: [1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 285, 360, 444, 536, 635, 740, 850, 964, 1081, 1200, 1319, 1436, 1550, 1660, 1765, 1864, 1956, 2040, 2115, 2180, 2235, 2280, 2316, 2344, 2365, 2380, 2390, 2396, 2399, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2399, 2396, 2390, 2380, 2365, 2344, 2316, 2280, 2235, 2180, 2115, 2040, 1956, 1864, 1765, 1660, 1550, 1436, 1319, 1200, 1081, 964, 850, 740, 635, 536, 444, 360, 285, 220, 165, 120, 84, 56, 35, 20, 10, 4, 1]
Mego
fonte
Sandbox
Mego

Respostas:

7

Geléia ,  14  7 bytes

-3 bytes, graças ao Sr. Xcoder (uso de um intervalo implícito para evitar a liderança R; substituição de redução pelo produto cartesiano diádico e achatamento p/F€, com o produto cartesiano incorporado para esse fim Œp).

ŒpS€ĠL€

Um link monádico que obtém uma lista de faces de dados e retorna a distribuição normalizada das somas crescentes.

Experimente online!

Quão?

Percorre a lista de "tamanhos" de dados (implicitamente) os coloca em sua lista de faces e, em seguida, obtém o produto cartesiano dessas listas (todos os possíveis lançamentos do conjunto de dados), depois resume esses rolos, obtém os grupos de iguais índices (por valor crescente) e mede a duração de cada grupo.

ŒpS€ĠL€ - Link: list of numbers, dice  e.g. [2,5,1,2]
Œp      - Cartisian product (implicit range-ification -> [[1,2],[1,2,3,4,5],[1],[1,2]])
        -                   -> [[1,1,1,1],[1,1,1,2],[1,2,1,1],[1,2,1,2],[1,3,1,1],[1,3,1,2],[1,4,1,1],[1,4,1,2],[1,5,1,1],[1,5,1,2],[2,1,1,1],[2,1,1,2],[2,2,1,1],[2,2,1,2],[2,3,1,1],[2,3,1,2],[2,4,1,1],[2,4,1,2],[2,5,1,1],[2,5,1,2]]
  S€    - sum €ach          -> [4,5,5,6,6,7,7,8,8,9,5,6,6,7,7,8,8,9,9,10]
    Ġ   - group indices     -> [[1],[2,3,11],[4,5,12,13],[6,7,14,15],[8,9,16,17],[10,18,19],[20]]
     L€ - length of €ach    -> [1,3,4,4,4,3,1]

Nota: existe apenas uma maneira de rolar o mínimo (rolando um em cada um dos dados) e não estamos contando duas rolagens, portanto, não há necessidade de executar uma normalização do GCD.

Jonathan Allan
fonte
Obrigado, eu estou querendo saber se alguma vez precisar da ÷g/$embora (não há sempre apenas uma maneira de obter o mínimo ou máximo?)
Jonathan Allan
2
Pensei que isso era uma alternativa interessante:ŒpS€µLƙ
Mr. Xcoder 10/12
5

MATL , 8 bytes

1i"@:gY+

A entrada é uma matriz de (possivelmente repetidos) tamanhos de matriz.

Experimente online! Ou verifique todos os casos de teste .

Explicação

1      % Push 1
i      % Input: numeric array
"      % For each k in that array
  @    %   Push k
  :    %   Range: gives [1 2 ... k]
  g    %   Convert to logical: gives [1 1 ... 1]
  Y+   %   Convolution, with full size
       % End (implicit). Display (implicit)
Luis Mendo
fonte
5

Casca , 7 bytes

mLkΣΠmḣ

Entrada é uma lista de dados. Experimente online!

Explicação

mLkΣΠmḣ  Implicit input, say x=[3,3,6].
     mḣ  Map range: [[1,2,3],[1,2,3],[1,2,3,4,5,6]]
    Π    Cartesian product: [[1,1,1],[1,1,2],..,[3,3,6]]
  kΣ     Classify by sum: [[[1,1,1]],[[1,1,2],[1,2,1],[2,1,1]],..,[[3,3,6]]]
mL       Map length: [1,3,6,8,9,9,8,6,3,1]
Zgarb
fonte
4

Oitava , 88 69 58 56 bytes

Como mencionado na resposta de Haskell, isso usa o fato de que a distribuição de, por exemplo, dados de 3 e 5 lados é a convolução discreta dos dois vetores [1,1,1]e [1,1,1,1,1]. Obrigado @LuisMendo por -11 bytes de golfe inteligente!

function y=f(c);y=1:c;if d=c(2:end);y=conv(~~y,f(d));end

Experimente online!

Este envio está usando uma abordagem recursiva. Mas se você usasse um loop, seria um pouco mais longo:

function y=f(c);y=1;for k=cellfun(@(x)ones(1,x),c,'Un',0);y=conv(y,k{1});end
flawr
fonte
4

Haskell , 80 78 64 bytes

Essa solução acabou sendo quase a mesma da @ Sherlock9 no desafio anterior, com a abordagem talvez mais natural. O @xnor possui uma solução Haskell ainda mais curta !

import Data.List
g x=[1..x]
map length.group.sort.map sum.mapM g

Explicação:

                              mapM g -- all possible outcomes
                      map sum        -- the sums of all possible outcomes
map length.group.sort                -- count the frequency of each sum

Experimente online!

Solução anterior:

Isso está usando a função de convolução discreta @AndersKaseorg . A observação aqui é que a distribuição de, por exemplo, dados de 3 e 5 lados é a convolução discreta dos dois vetores [1,1,1]e [1,1,1,1,1].

foldl1(#).map(`take`l)
(a:b)#c=zipWith(+)(0:b#c)$map(a*)c++[]#b
_#c=0<$c
l=1:l

Experimente online!

flawr
fonte
4

Wolfram Language (Mathematica) , 26 bytes

Tally[Tr/@Tuples@Range@#]&

Experimente online!

Uma modificação da minha resposta ao desafio anterior . Isso apenas gera todos os resultados possíveis, os soma e registra os resultados.

Por diversão, poderíamos escrever como Tally@*Total@*Thread@*Tuples@*Range, mas é mais longo.

Wolfram Language (Mathematica) , 41 bytes

CoefficientList[1##&@@((x^#-1)/(x-1)),x]&

Experimente online!

Essa é a abordagem baseada em convolução (aqui, fazemos convoluções por meio do produto de funções geradoras - 1+x+x^2+...+x^(N-1)é a função geradora para rolar um dN - e, em seguida, tomamos a lista de coeficientes). Eu o incluo porque a primeira solução não é prática para grandes entradas.

Misha Lavrov
fonte
4

Mathematica, 44 bytes

Emite as frequências rotuladas com as somas correspondentes

Tally@*Fold[Join@@Table[#+i,{i,#2}]&]@*Range

Experimente online!

-5 bytes de Martin Ender

obrigado a Misha Lavrov por me informar que "rotulado" é válido

J42161217
fonte
3

Pitão , 12 bytes

lM.gs.nk*FSM

Experimente aqui!

Quão?

lM.gs.nk * FSM ~ Programa completo.

          SM ~ Mapa com intervalo inteiro unário inclusivo [1, N].
        * F ~ Fold (Reduzir em) produto cartesiano.
  .g ~ Agrupar por resultado da função.
    sn ~ A soma da lista quando nivelada.
Comprimento de cada grupo.
Mr. Xcoder
fonte
3

Gelatina , 14 bytes

R+Ѐ/FċЀSR$ḟ0

Experimente online!

Entrada é uma lista de valores de matriz. Eu poderia jogar isso roubando ĠL€a outra resposta do Jelly, mas então eu também poderia jogar no primeiro semestre e acabar com a mesma coisa, então vou deixar como está

dylnan
fonte
2

Python 2 , 120 119 bytes

lambda v:[reduce(lambda a,c:sum([[b+y for b in a]for y in range(c)],[]),v,[0]).count(d)for d in range(sum(v)-len(v)+1)]

Experimente online!

Obrigado por Mego / Jonathon Allan por 1 byte.

Chas Brown
fonte
... ou seja, salve um byte .
Jonathan Allan
2

05AB1E , 11 bytes

€L.«âOO{γ€g

Experimente online!

Como funciona

€ L - g - Programa completo.

€ L - Para cada N da lista, obtenha [1 .. N].
  . «- Dobre uma função diádica entre cada elemento de uma lista da direita para a esquerda.
    â - E escolha o produto cartesiano como essa função.
     O - Achate cada um.
      O - Soma cada.
       {γ - Classifique e agrupe em execuções de valores adjacentes iguais.
         € g - Obtenha os comprimentos de cada um.

Guardado 1 byte graças a Emigna !

Mr. Xcoder
fonte
Você poderia fazer em Ovez de€˜
Emigna
2

R , 51 bytes

function(D){for(x in D)F=outer(F,1:x,"+")
table(F)}

Experimente online!

Pega uma lista de dados e retorna um vetor nomeado de frequências; os nomes (valores da soma dos dados) são impressos acima das frequências.

R , 59 bytes

function(D)table(Reduce(function(x,y)outer(x,1:y,"+"),D,0))

Experimente online!

Uma Reduceabordagem, e não a iterativa acima.

R , 62 bytes

function(D)Re(convolve(!!1:D,"if"(sum(x<-D[-1]),f(x),1),,"o"))

Experimente online!

Uma abordagem de convolução. Ele fornecerá alguns avisos de que está apenas usando o primeiro elemento de Dpara a expressão, 1:Dmas não afeta a saída. Se não tivéssemos que pegar toda a Reparte da solução, seriam 58 bytes.

Giuseppe
fonte
1

APL (Dyalog Classic) , 12 10 bytes

-2 graças a @ Adám

⊢∘≢⌸+/↑,⍳⎕

Experimente online!

a entrada é uma lista de N dados

⍳⍵ é uma matriz N-dimensional de vetores aninhados - todos os arremessos de matriz possíveis

+/↑, nivela as matrizes e soma os arremessos

⊢∘≢⌸ conta quantos de cada soma exclusiva, listados em ordem de primeira aparição, que felizmente coincidem com a ordem crescente

ngn
fonte
11
-2: ⊢∘≢⌸+/↑,⍳⎕
Adám
1

Ruby , 72 bytes

->d{r=[0]*d.sum
[0].product(*d.map{|e|[*1..e]}){|e|r[e.sum-1]+=1}
r-[0]}

Experimente online!

Leva uma lista de dados como entrada. Sem dúvida, pode ser jogado para baixo, mas não tão ruim.

Restabelecer Monica iamnotmaynard
fonte
0

Limpo , 154 142 136 107 100 85 + 13 = 98 bytes

Entrada é uma lista de dados.

\l#t=foldr(\a-> \b=[x+y\\x<-[1..a],y<-b])[0]l
=[length[v\\v<-t|u==v]\\u<-removeDup t]

A resposta está na forma de uma lambda.

+13 bytes de import StdEnv, que importa o módulo necessário para que isso funcione.

Experimente online!

Furioso
fonte
0

JavaScript (ES6), 83 bytes

f=(n,...a)=>n?f(...a).map((e,i)=>[...Array(n)].map(_=>r[i]=~~r[i++]+e),r=[])&&r:[1]
g=s=>o.textContent=f(...(s.match(/\d+/g)||[]).map(n=>+n)).join`, `
<input oninput=g(this.value)><p id=o>1

Recebe a entrada de cada dado como um parâmetro separado.

Neil
fonte
0

JavaScript (ES6), 76 74 bytes

Toma entrada como uma lista de dados.

a=>(g=k=>a.map(d=>(s+=n%d|0,n/=d),s=0,n=k)|n?x:g(k+1,x[s]=-~x[s]))(0,x=[])

Casos de teste

O processamento dos dois últimos casos de teste exigiria ativar o TCO ou aumentar o limite de tamanho da pilha padrão do mecanismo JS.

Formatado e comentado

NB: Esta é uma versão comentada do meu envio inicial que estava usando reduza (). É 2 bytes mais longo, mas mais fácil de ler.

a =>                    // given the list of dice a
  (g = k =>             // g = recursive function taking k = counter
    a.reduce((k, d) =>  //   for each die d in a:
      (                 //     k % d represents the current face of d
        s += k % d,     //     we add it to the total s
        k / d | 0       //     and we update k to pick the face of the next die
      ),                //     initialization:
      k,                //     start with the current value of k
      s = 0             //     total = 0
    ) ?                 //   reduce() returns 1 as soon as k = product of all dice
      x                 //     in which case we're done: stop recursion and return x
    :                   //   else:
      g(                //     do a recursive call to g() with:
        k + 1,          //       k incremented
        x[s] = -~x[s]   //       x[s] incremented
      )                 //     end of recursive call
  )(0, x = [])          // initial call to g() with k = 0 and x = empty array
Arnauld
fonte
0

Clojure, 96 bytes

#(sort-by key(frequencies(reduce(fn[R D](for[d(range D)r R](+ r d 1)))[0](mapcat repeat % %2))))

A primeira entrada é uma lista do número de dados e a segunda entrada é uma lista do número de lados em cada dado.

NikoNyrh
fonte
0

Perl 5 , 94 bytes

map$k{$_}++,map eval,glob join'+',map'{'.(join',',1..$_).'}',<>;say$k{$_}for sort{$a-$b}keys%k

Experimente online!

O formato de entrada é uma lista de dados separados por novas linhas. Assim, 1d10 + 2d8 digitaria como:

10
8
8
Xcali
fonte
0

SageMath, 46 bytes

lambda*a:reduce(convolution,[x*[1]for x in a])

Experimente online

Esta é uma adaptação da minha solução para o outro desafio . Ele recebe qualquer número de dados como parâmetros (por exemplo, f(4,4,6,6,6)para 2d4+3d6) e retorna uma lista.


Python 2 + NumPy , 62 bytes

lambda*a:reduce(numpy.convolve,[x*[1]for x in a])
import numpy

Experimente online!

Como antes, incluímos esta solução na acima, pois são essencialmente equivalentes. Observe que essa função retorna uma matriz NumPy e não uma lista Python; portanto, a saída parece um pouco diferente se você a printusar.

numpy.ones(x)é a maneira "correta" de criar uma matriz para uso com o NumPy e, portanto, pode ser usada no lugar de [x*[1]], mas infelizmente é muito mais longa.

Mego
fonte