Rozkład częstotliwości mieszanych rzutów kostką

24

Kontynuacja tego wyzwania

Biorąc pod uwagę zestaw mieszanych kości, generuj rozkład częstotliwości rzucania nimi wszystkimi i sumowania liczb rzucanych na każdej kości.

Rozważmy na przykład 1d12 + 1d8(rzucenie 1 matrycą 12-stronną i 1 matrycą 8-stronną). Maksymalne i minimalne rolki są 20i 2, odpowiednio, który jest podobny do walcowania 2d10(2 10 kostkami). Jednak 1d12 + 1d8powoduje bardziej płaski rozkład niż 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].

Zasady

  • Częstotliwości muszą być wymienione w kolejności rosnącej od sumy, której częstotliwość odpowiada.
  • Oznaczanie częstotliwości odpowiednimi sumami jest dozwolone, ale nie wymagane (ponieważ sumy można wywnioskować z wymaganej kolejności).
  • Nie musisz obsługiwać danych wejściowych, w których dane wyjściowe przekraczają reprezentatywny zakres liczb całkowitych dla Twojego języka.
  • Zera wiodące lub końcowe są niedozwolone. Na wyjściu powinny pojawić się tylko dodatnie częstotliwości.
  • Możesz wziąć dane wejściowe w dowolnym rozsądnym formacie (lista kości ( [6, 8, 8]), lista par kości ( [[1, 6], [2, 8]]) itp.).
  • Częstotliwości muszą zostać znormalizowane, aby GCD częstotliwości wynosił 1 (np. [1, 2, 3, 2, 1]Zamiast [2, 4, 6, 4, 2]).
  • Wszystkie kości będą miały co najmniej jedną twarz (więc d1jest to minimum).
  • To jest , więc wygrywa najkrótszy kod (w bajtach). Standardowe luki są zabronione, jak zwykle.

Przypadki testowe

Te przypadki testowe są podane jako input: output, gdzie dane wejściowe są podane jako lista par [a, b]reprezentujących a bkostki jednostronne (tak [3, 8]odnosi się 3d8i [[1, 12], [1, 8]]odnosi się do 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
źródło

Odpowiedzi:

7

Galaretka ,  14  7 bajtów

-3 bajty dzięki Panu Xcoderowi (użycie domyślnego zakresu, aby uniknąć wiodącego R; zastąpienie zmniejszonego przez diadetyczny produkt kartezjański i spłaszczenie p/F€, z wbudowanym w tym celu produktem kartezjańskim Œp).

ŒpS€ĠL€

Monadyczny link pobierający listę kości do gry i zwracający znormalizowany rozkład rosnących sum.

Wypróbuj online!

W jaki sposób?

Przechodzi przez listę „rozmiarów” kości (domyślnie) umieszcza je na swojej liście twarzy, następnie pobiera iloczyn kartezjański tych list (wszystkie możliwe rzuty zestawu kości), następnie podsumowuje te rzuty, uzyskuje grupy równych indeksy (według wartości rosnącej) i przyjmuje długość każdej grupy.

Œ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]

Uwaga: istnieje tylko jeden sposób, aby rzucić minimum (rzucając jeden na każdą kostkę) i nie liczymy żadnych rzutów, więc nie ma potrzeby wykonywania normalizacji GCD.

Jonathan Allan
źródło
Dzięki, zastanawiam się, czy kiedykolwiek potrzebujemy ÷g/$(choć nie zawsze jest tylko jeden sposób na uzyskanie wartości minimalnej lub maksymalnej?)
Jonathan Allan,
2
Pomyślałem, że to warta podzielenia się alternatywa:ŒpS€µLƙ
Pan Xcoder,
5

MATL , 8 bajtów

1i"@:gY+

Dane wejściowe to tablica (ewentualnie powtarzanych) rozmiarów matryc.

Wypróbuj online! Lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie

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
źródło
5

Łuska , 7 bajtów

mLkΣΠmḣ

Dane wejściowe to lista kości. Wypróbuj online!

Wyjaśnienie

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
źródło
4

Oktawa , 88 69 58 56 bajtów

Jak wspomniano w odpowiedzi Haskella, wykorzystuje to fakt, że rozkład np. Kostek 3-stronnych i 5-stronnych jest dyskretnym splotem dwóch wektorów [1,1,1]i [1,1,1,1,1]. Dzięki @LuisMendo za -11 bajtów za sprytne granie w golfa!

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

Wypróbuj online!

To przesłanie wykorzystuje podejście rekurencyjne. Ale jeśli użyjesz pętli, będzie ona nieco dłuższa:

function y=f(c);y=1;for k=cellfun(@(x)ones(1,x),c,'Un',0);y=conv(y,k{1});end
wada
źródło
4

Haskell , 80 78 64 bajtów

To rozwiązanie okazało się prawie takie samo jak rozwiązanie @ Sherlock9 w poprzednim wyzwaniu, z być może bardziej naturalnym podejściem. @xnor ma jeszcze krótsze rozwiązanie Haskell !

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

Wyjaśnienie:

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

Wypróbuj online!

Poprzednie rozwiązanie:

Wykorzystuje to funkcję dyskretnego splotu @AndersKaseorg . Obserwacja tutaj jest taka, że ​​rozkład np. Kostek 3-stronnych i 5-stronnych jest dyskretnym splotem dwóch wektorów [1,1,1]i [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

Wypróbuj online!

wada
źródło
4

Wolfram Language (Mathematica) , 26 bajtów

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

Wypróbuj online!

Modyfikacja mojej odpowiedzi na poprzednie wyzwanie . To po prostu generuje wszystkie możliwe wyniki, sumuje je i ocenia wyniki.

Dla zabawy możemy to napisać jako Tally@*Total@*Thread@*Tuples@*Range, ale to dłużej.

Wolfram Language (Mathematica) , 41 bajtów

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

Wypróbuj online!

Jest to podejście oparte na splotach (tutaj bierzemy splot poprzez iloczyn funkcji generujących - 1+x+x^2+...+x^(N-1)jest to funkcja generująca dla zwijania dN - a następnie przyjmujemy listę współczynników). Uwzględniam to, ponieważ pierwsze rozwiązanie nie jest praktyczne w przypadku dużych nakładów.

Misza Ławrow
źródło
4

Mathematica, 44 bajty

Wysyła częstotliwości oznaczone odpowiednimi sumami

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

Wypróbuj online!

-5 bajtów od Martina Endera

dziękuję Miszy Ławrow za poinformowanie mnie, że „oznaczone” jest ważne

J42161217
źródło
3

Pyth , 12 bajtów

lM.gs.nk*FSM

Wypróbuj tutaj!

W jaki sposób?

lM.gs.nk * FSM ~ Pełny program.

          SM ~ Mapa zawierająca jednokierunkowy zakres liczb całkowitych [1, N].
        * F ~ Fold (Zmniejsz o) Produkt kartezjański.
  .g ~ Grupuj według wyniku funkcji.
    sn ~ Suma listy po spłaszczeniu.
lM ~ Długość każdej grupy.
Pan Xcoder
źródło
3

Galaretka , 14 bajtów

R+Ѐ/FċЀSR$ḟ0

Wypróbuj online!

Dane wejściowe to lista wartości matryc. Mógłbym zagrać w golfa, wykradając się ĠL€z drugiej odpowiedzi Jelly, ale potem mogłem też zagrać w golfa w pierwszej połowie i skończyć z tym samym, więc zostawię to tak, jak jest

dylnan
źródło
2

Python 2 , 120 119 bajtów

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)]

Wypróbuj online!

Dziękujemy za Mego / Jonathon Allan za 1 bajt.

Chas Brown
źródło
... tj. zapisz bajt .
Jonathan Allan,
2

05AB1E , 11 bajtów

€L.«âOO{γ€g

Wypróbuj online!

Jak to działa

€ L. «âOO {γ € g - Pełny program.

€ L - Za każdy N na liście otrzymaj [1 .. N].
  . «- Złożyć funkcję dyadyczną między każdym elementem na liście od prawej do lewej.
    â - I wybierz produkt kartezjański jako tę funkcję.
     O - Spłaszcz każdy.
      O - Suma każdego.
       {γ - Sortuj i grupuj w serie o równych sąsiadujących wartościach.
         € g - Uzyskaj długości każdego z nich.

Zaoszczędzono 1 bajt dzięki Emignie !

Pan Xcoder
źródło
Możesz zrobić Ozamiast€˜
Emigna,
2

R , 51 bajtów

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

Wypróbuj online!

Pobiera listę kości i zwraca nazwany wektor częstotliwości; nazwy (wartości sum kości) są drukowane powyżej częstotliwości.

R , 59 bajtów

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

Wypróbuj online!

ReducePodejście zamiast iteracyjny jeden powyżej.

R , 62 bajty

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

Wypróbuj online!

Podejście splotowe. Daje kilka ostrzeżeń, że używa tylko pierwszego elementu Dwyrażenia, 1:Dale nie wpływa na wynik. Gdybyśmy nie musieli wziąć całej Reczęści rozwiązania, byłoby to 58 bajtów.

Giuseppe
źródło
1

APL (Dyalog Classic) , 12 10 bajtów

-2 dzięki @ Adám

⊢∘≢⌸+/↑,⍳⎕

Wypróbuj online!

wejście to lista N kości

⍳⍵ to N-wymiarowa tablica zagnieżdżonych wektorów - wszystkie możliwe rzuty

+/↑, spłaszcza tablice i sumuje rzuty

⊢∘≢⌸ liczy, ile z każdej unikalnej sumy, wymienionych w kolejności pierwszego pojawienia się, co na szczęście pokrywa się z ich rosnącą kolejnością

ngn
źródło
1
-2: ⊢∘≢⌸+/↑,⍳⎕
Adám
1

Rubinowy , 72 bajty

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

Wypróbuj online!

Pobiera na wejściu listę kości. Bez wątpienia można go zagrać w golfa, ale nie jest tak źle.

Przywróć Monikę iamnotmaynard
źródło
0

Czysty , 154 142 136 107 100 85 + 13 = 98 bajtów

Dane wejściowe to lista kości.

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

Odpowiedź ma postać lambda.

+13 bajtów, z import StdEnvktórych importuje moduł potrzebny do tego, aby działał.

Wypróbuj online!

Obrzydliwe
źródło
0

JavaScript (ES6), 83 bajty

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

Pobiera dane wejściowe każdej kości jako osobny parametr.

Neil
źródło
0

JavaScript (ES6), 76 74 bajtów

Pobiera dane wejściowe jako listę kości.

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=[])

Przypadki testowe

Przetwarzanie dwóch ostatnich przypadków testowych wymagałoby włączenia TCO lub zwiększenia domyślnego limitu wielkości stosu silnika JS.

Sformatowane i skomentowane

Uwaga: To jest skomentowana wersja mojego pierwszego przesłania, która używała metody redukcyjnej (). Jest o 2 bajty dłuższy, ale łatwiejszy do odczytania.

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
źródło
0

Clojure, 96 bajtów

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

Pierwsze wejście to lista liczby kości, a drugie wejście to lista stron na każdej kości.

NikoNyrh
źródło
0

Perl 5 , 94 bajtów

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

Wypróbuj online!

Format wejściowy to lista kości oddzielonych znakami nowej linii. Zatem 1d10 + 2d8 wprowadziłby jako:

10
8
8
Xcali
źródło
0

SageMath, 46 bajtów

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

Wypróbuj online

Jest to dostosowanie mojego rozwiązania do drugiego wyzwania . Pobiera dowolną liczbę kostek jako parametry (np. f(4,4,6,6,6)Dla 2d4+3d6) i zwraca listę.


Python 2 + NumPy , 62 bajty

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

Wypróbuj online!

Tak jak poprzednio, dołączyłem to rozwiązanie do powyższego, ponieważ są one zasadniczo równoważne. Zauważ, że ta funkcja zwraca tablicę NumPy, a nie listę Pythona, więc dane wyjściowe wyglądają nieco inaczej print.

numpy.ones(x)jest „poprawnym” sposobem na stworzenie tablicy do użycia z NumPy, a zatem może być używana zamiast [x*[1]], ale niestety jest znacznie dłuższa.

Mego
źródło